Skip to content

feat(webapp): allow marking env vars as secret after creation - #2969

Open
JoanLaRosa wants to merge 2 commits into
triggerdotdev:mainfrom
JoanLaRosa:feat/make-env-var-secret
Open

feat(webapp): allow marking env vars as secret after creation#2969
JoanLaRosa wants to merge 2 commits into
triggerdotdev:mainfrom
JoanLaRosa:feat/make-env-var-secret

Conversation

@JoanLaRosa

@JoanLaRosa JoanLaRosa commented Jan 29, 2026

Copy link
Copy Markdown

Summary

  • Add an irreversible "Make secret" toggle to the edit environment variable dialog
  • The toggle is part of the edit form and submits on Save (not as a separate request)
  • Once toggled on and saved, the value is hidden and the switch becomes disabled — it cannot be reverted
  • Adds an optional isSecret field to the editValue repository method and Zod schema
  • Removes the standalone makeSecret action in favor of the unified form-based approach

Implements: https://feedback.trigger.dev/p/ability-to-set-a-non-secret-env-var-to-secret

Tested on local:

Before saving:
image
After saving:
image


Open with Devin

@changeset-bot

changeset-bot Bot commented Jan 29, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: da75a16

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Jan 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0a3d8a1f-5110-4886-8f91-af3438106536

📥 Commits

Reviewing files that changed from the base of the PR and between 8c97d18 and da75a16.

📒 Files selected for processing (3)
  • .server-changes/mark-environment-variables-secret.md
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (10)
New code must target Run Engine V2 through the singleton in `app/v3/runEngine.server.ts`; do not reintroduce V1 execution paths. V1 branches may only reject or finalize gracefully with a clean 4xx.

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
Never use `request.signal` to detect client disconnects. Use `getRequestAbortSignal()` from `app/services/httpAsyncStorage.server.ts`, which is wired to Express response close events.

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
For dashboard changes, visually verify the running Remix app with Chrome DevTools MCP, using snapshots, screenshots, interaction, and console-message checks as appropriate.

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts
**Prefer static imports over dynamic imports.** Only use dynamic `import()` when:

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts
Add crumbs as you write code — not just when debugging. Mark lines with

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts
Use zod for validation in packages/core and apps/webapp

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts
Access environment variables through the `env` export of `env.server.ts` instead of directly accessing `process.env`

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts
Use function declarations instead of default exports

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts
Use types over interfaces for TypeScript

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts
When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

Files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
🧠 Learnings (1)
📚 Learning: 2026-07-26T13:14:02.968Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 4378
File: .server-changes/realtime-run-reads-from-primary.md:0-0
Timestamp: 2026-07-26T13:14:02.968Z
Learning: For files in the .server-changes directory, the body text is published verbatim as dashboard-facing user release notes. Write entries in terms of user-visible behavior (what users can do/see), and avoid implementation-oriented details such as environment-variable names, internal mechanisms, or configuration knobs. If you need to include operational/configuration specifics, put those details in the PR description instead of the .server-changes entry.

Applied to files:

  • .server-changes/mark-environment-variables-secret.md
🔇 Additional comments (8)
apps/webapp/app/v3/environmentVariables/repository.ts (1)

72-75: LGTM!

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx (6)

23-31: LGTM!


47-47: LGTM!


820-845: LGTM!


865-873: LGTM!


929-933: LGTM!


892-907: 🔒 Security & Privacy

No change needed. EnvironmentVariablesPresenter.server.ts sets value to "" when isSecret is true, so defaultValue={variable.value} does not expose the stored secret.

.server-changes/mark-environment-variables-secret.md (1)

1-6: LGTM!


Walkthrough

The environment variable edit flow now tracks and submits isSecret. The edit panel resets secret state when it opens, confirms conversion to a secret, and prevents submission if confirmation is declined. Existing secret variables remain disabled. The validation preprocessing preserves an omitted isSecret field. The repository marks the updated value as secret when isSecret is truthy. A feature changelog entry documents the dashboard action.

Merge Risk: ⚪ Minimal · up to da75a

The change is localized to marking environment variables as secret, and no actionable merge-blocking risk remains after normal checks and review.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 3 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: allowing existing environment variables to be marked as secret.
Description check ✅ Passed The description explains the feature, implementation changes, irreversible behavior, testing performed, changelog impact, and screenshots. It does not include the template checklist or a Closes issue …
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description explains the feature, implementation changes, irreversible behavior, testing performed, changelog impact, and screenshots. It does not include the template checklist or a Closes issue line, but the required change details are mostly complete.

Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 3 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@vibe-kanban-cloud

Copy link
Copy Markdown

Review Complete

Your review story is ready!

View Story

Comment !reviewfast on this PR to re-generate the story.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

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

⚠️ Outside diff range comments (1)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx (1)

425-524: Close dialog and clear input value after makeSecret succeeds.

The input field uses defaultValue={variable.value}, so when makeSecret succeeds and marks the variable as secret, the previous value remains visible in the uncontrolled input. Additionally, the dialog doesn't close after makeSecret completes (only after edit actions). Add a handler to track the secret state change and close the dialog:

Suggested fix
  const fetcher = useFetcher<typeof action>();
  const makeSecretFetcher = useFetcher<typeof action>();
  const lastSubmission = fetcher.data as any;

  const isLoading = fetcher.state !== "idle";
  const isMakingSecret = makeSecretFetcher.state !== "idle";
+ const isSecretNow = variable.isSecret || makeSecretFetcher.data?.success;

  // Close dialog on successful submission
  useEffect(() => {
    if (lastSubmission?.success && fetcher.state === "idle") {
      setIsOpen(false);
    }
  }, [lastSubmission?.success, fetcher.state]);
+
+ useEffect(() => {
+   if (makeSecretFetcher.data?.success && makeSecretFetcher.state === "idle") {
+     setIsOpen(false);
+   }
+ }, [makeSecretFetcher.data?.success, makeSecretFetcher.state]);

  const [form, { id, environmentId, value }] = useForm({
    id: `edit-environment-variable-${variable.id}-${variable.environment.id}`,
    // TODO: type this
    lastSubmission: lastSubmission as any,
    onValidate({ formData }) {
      return parse(formData, { schema });
    },
    shouldRevalidate: "onSubmit",
  });

Then update the input and switch to reflect the immediate secret state:

  <Input
    {...conform.input(value, { type: "text" })}
    placeholder={variable.isSecret ? "Set new secret value" : "Not set"}
-   defaultValue={variable.value}
+   key={`${variable.id}-${variable.environment.id}-${isSecretNow ? "secret" : "plain"}`}
+   defaultValue={isSecretNow ? "" : variable.value}
    type={"text"}
  />
  <Switch
    variant="medium"
    label={<span className="text-text-bright">Secret value</span>}
-   checked={variable.isSecret}
-   disabled={variable.isSecret || isMakingSecret}
+   checked={isSecretNow}
+   disabled={isSecretNow || isMakingSecret}
    onCheckedChange={(checked) => {
      if (checked) {
        handleMakeSecret();
      }
    }}
  />
  <Hint>
-   {variable.isSecret
+   {isSecretNow
      ? "This variable is secret and cannot be changed back."
      : "Once enabled, the value will be hidden and cannot be revealed again."}
  </Hint>
🧹 Nitpick comments (1)
apps/webapp/app/v3/environmentVariables/repository.ts (1)

92-115: Prefer a type alias over an interface for Repository.

Since this change extends the interface, consider converting it to a type alias to match the TS style guideline.

♻️ Proposed refactor
-export interface Repository {
+export type Repository = {
   create(projectId: string, options: CreateEnvironmentVariables): Promise<CreateResult>;
   edit(projectId: string, options: EditEnvironmentVariable): Promise<Result>;
   editValue(projectId: string, options: EditEnvironmentVariableValue): Promise<Result>;
   getProject(projectId: string): Promise<ProjectEnvironmentVariable[]>;
   /**
    * Get the environment variables for a given environment, it does NOT return values for secret variables
    */
   getEnvironmentWithRedactedSecrets(
     projectId: string,
     environmentId: string
   ): Promise<EnvironmentVariableWithSecret[]>;
   /**
    * Get the environment variables for a given environment
    */
   getEnvironment(projectId: string, environmentId: string): Promise<EnvironmentVariable[]>;
   /**
    * Return all env vars, including secret variables with values. Should only be used for executing tasks.
    */
   getEnvironmentVariables(projectId: string, environmentId: string): Promise<EnvironmentVariable[]>;
   delete(projectId: string, options: DeleteEnvironmentVariable): Promise<Result>;
   deleteValue(projectId: string, options: DeleteEnvironmentVariableValue): Promise<Result>;
   makeSecret(projectId: string, options: MakeSecretEnvironmentVariableValue): Promise<Result>;
-}
+};

As per coding guidelines: Use types over interfaces for TypeScript.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0674d74 and f717869.

📒 Files selected for processing (3)
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
  • apps/webapp/app/v3/environmentVariables/repository.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

**/*.{ts,tsx}: Always import tasks from @trigger.dev/sdk, never use @trigger.dev/sdk/v3 or deprecated client.defineJob pattern
Every Trigger.dev task must be exported and have a unique id property with no timeouts in the run function

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Import from @trigger.dev/core using subpaths only, never import from root

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Access environment variables via env export from apps/webapp/app/env.server.ts, never use process.env directly

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries

Files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
🧠 Learnings (6)
📓 Common learnings
Learnt from: julienvanbeveren
Repo: triggerdotdev/trigger.dev PR: 2417
File: apps/webapp/app/routes/api.v1.projects.$projectRef.envvars.$slug.import.ts:56-61
Timestamp: 2025-08-19T09:49:07.011Z
Learning: In the Trigger.dev codebase, environment variables should default to `isSecret: false` when not explicitly marked as secrets in the syncEnvVars functionality. This is the intended behavior for both regular variables and parent variables.
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/app/**/*.{ts,tsx} : Access all environment variables through the `env` export of `env.server.ts` instead of directly accessing `process.env` in the Trigger.dev webapp
Learnt from: nicktrn
Repo: triggerdotdev/trigger.dev PR: 2155
File: hosting/docker/.env.example:4-7
Timestamp: 2025-06-06T23:55:01.933Z
Learning: In the trigger.dev project, .env.example files should contain actual example secret values rather than placeholders, as these help users understand the expected format. The files include clear warnings about not using these defaults in production and instructions for generating proper secrets.
📚 Learning: 2025-12-08T15:19:56.823Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2760
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx:278-281
Timestamp: 2025-12-08T15:19:56.823Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx, the tableState search parameter uses intentional double-encoding: the parameter value contains a URL-encoded URLSearchParams string, so decodeURIComponent(value("tableState") ?? "") is required to fully decode it before parsing with new URLSearchParams(). This pattern allows bundling multiple filter/pagination params as a single search parameter.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/app/**/*.{ts,tsx} : Access all environment variables through the `env` export of `env.server.ts` instead of directly accessing `process.env` in the Trigger.dev webapp

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
📚 Learning: 2025-04-17T10:27:25.337Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 1923
File: packages/core/src/v3/schemas/api.ts:813-827
Timestamp: 2025-04-17T10:27:25.337Z
Learning: Creating secret environment variables is restricted to the dashboard UI only, and not allowed via the API/SDK for now. The `EnvironmentVariableWithSecret` type in the API schema is for reading/displaying purposes only.

Applied to files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : Access environment variables via `env` export from `apps/webapp/app/env.server.ts`, never use `process.env` directly

Applied to files:

  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
📚 Learning: 2025-08-19T09:49:07.011Z
Learnt from: julienvanbeveren
Repo: triggerdotdev/trigger.dev PR: 2417
File: apps/webapp/app/routes/api.v1.projects.$projectRef.envvars.$slug.import.ts:56-61
Timestamp: 2025-08-19T09:49:07.011Z
Learning: In the Trigger.dev codebase, environment variables should default to `isSecret: false` when not explicitly marked as secrets in the syncEnvVars functionality. This is the intended behavior for both regular variables and parent variables.

Applied to files:

  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
🧬 Code graph analysis (3)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx (1)
apps/webapp/app/v3/environmentVariables/repository.ts (2)
  • MakeSecretEnvironmentVariableValue (50-53)
  • MakeSecretEnvironmentVariableValue (54-54)
apps/webapp/app/v3/environmentVariables/repository.ts (1)
apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts (1)
  • projectId (584-624)
apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts (1)
apps/webapp/app/v3/environmentVariables/repository.ts (3)
  • MakeSecretEnvironmentVariableValue (50-53)
  • MakeSecretEnvironmentVariableValue (54-54)
  • Result (63-70)
🔇 Additional comments (5)
apps/webapp/app/v3/environmentVariables/repository.ts (1)

50-54: MakeSecretEnvironmentVariableValue schema looks good.

The payload shape aligns with the new action and keeps validation consistent.

apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts (2)

8-18: No review needed for the type import.


634-702: makeSecret flow looks solid.

Guards cover missing project, missing value, and already-secret states before the update.

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx (2)

31-31: No review needed for this import change.


109-198: Schema and action wiring for makeSecret are consistent.

The discriminated union and action handler stay aligned with the repository method.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@JoanLaRosa
JoanLaRosa force-pushed the feat/make-env-var-secret branch from f717869 to 3a2939b Compare January 29, 2026 15:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

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

⚠️ Outside diff range comments (2)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx (2)

406-418: Reset isSecret when the dialog opens to avoid unintended irreversible changes.
If a user toggles to secret and cancels, the state stays true; a later save can silently mark it secret.

🛠️ Suggested fix
   const [isOpen, setIsOpen] = useState(false);
   const [isSecret, setIsSecret] = useState(variable.isSecret);
   const fetcher = useFetcher<typeof action>();
   const lastSubmission = fetcher.data as any;

   const isLoading = fetcher.state !== "idle";

+  useEffect(() => {
+    if (isOpen) {
+      setIsSecret(variable.isSecret);
+    }
+  }, [isOpen, variable.isSecret]);

439-474: Add a confirmation gate before making a variable secret.
The action is irreversible, but the current submit flow doesn’t confirm the change.

🛠️ Suggested fix
   const isLoading = fetcher.state !== "idle";
+  const shouldConfirmSecret = !variable.isSecret && isSecret;
@@
-        <fetcher.Form method="post" {...form.props}>
+        <fetcher.Form
+          method="post"
+          {...form.props}
+          onSubmit={(event) => {
+            if (
+              shouldConfirmSecret &&
+              !window.confirm("Making this value secret is irreversible. Continue?")
+            ) {
+              event.preventDefault();
+            }
+          }}
+        >
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f717869 and 3a2939b.

📒 Files selected for processing (3)
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
  • apps/webapp/app/v3/environmentVariables/repository.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

**/*.{ts,tsx}: Always import tasks from @trigger.dev/sdk, never use @trigger.dev/sdk/v3 or deprecated client.defineJob pattern
Every Trigger.dev task must be exported and have a unique id property with no timeouts in the run function

Files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Import from @trigger.dev/core using subpaths only, never import from root

Files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Access environment variables via env export from apps/webapp/app/env.server.ts, never use process.env directly

Files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries

Files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
🧠 Learnings (8)
📓 Common learnings
Learnt from: julienvanbeveren
Repo: triggerdotdev/trigger.dev PR: 2417
File: apps/webapp/app/routes/api.v1.projects.$projectRef.envvars.$slug.import.ts:56-61
Timestamp: 2025-08-19T09:49:07.011Z
Learning: In the Trigger.dev codebase, environment variables should default to `isSecret: false` when not explicitly marked as secrets in the syncEnvVars functionality. This is the intended behavior for both regular variables and parent variables.
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 1923
File: packages/core/src/v3/schemas/api.ts:813-827
Timestamp: 2025-04-17T10:27:25.337Z
Learning: Creating secret environment variables is restricted to the dashboard UI only, and not allowed via the API/SDK for now. The `EnvironmentVariableWithSecret` type in the API schema is for reading/displaying purposes only.
📚 Learning: 2025-08-14T18:35:44.370Z
Learnt from: nicktrn
Repo: triggerdotdev/trigger.dev PR: 2390
File: apps/webapp/app/env.server.ts:764-765
Timestamp: 2025-08-14T18:35:44.370Z
Learning: The BoolEnv helper in apps/webapp/app/utils/boolEnv.ts uses z.preprocess with inconsistent default value types across the codebase - some usages pass boolean defaults (correct) while others pass string defaults (incorrect), leading to type confusion. The helper should enforce boolean-only defaults or have clearer documentation.

Applied to files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
📚 Learning: 2025-08-19T09:49:07.011Z
Learnt from: julienvanbeveren
Repo: triggerdotdev/trigger.dev PR: 2417
File: apps/webapp/app/routes/api.v1.projects.$projectRef.envvars.$slug.import.ts:56-61
Timestamp: 2025-08-19T09:49:07.011Z
Learning: In the Trigger.dev codebase, environment variables should default to `isSecret: false` when not explicitly marked as secrets in the syncEnvVars functionality. This is the intended behavior for both regular variables and parent variables.

Applied to files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/app/**/*.{ts,tsx} : Access all environment variables through the `env` export of `env.server.ts` instead of directly accessing `process.env` in the Trigger.dev webapp

Applied to files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : Access environment variables via `env` export from `apps/webapp/app/env.server.ts`, never use `process.env` directly

Applied to files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to {packages/core,apps/webapp}/**/*.{ts,tsx} : Use zod for validation in packages/core and apps/webapp

Applied to files:

  • apps/webapp/app/v3/environmentVariables/repository.ts
📚 Learning: 2025-12-08T15:19:56.823Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2760
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx:278-281
Timestamp: 2025-12-08T15:19:56.823Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx, the tableState search parameter uses intentional double-encoding: the parameter value contains a URL-encoded URLSearchParams string, so decodeURIComponent(value("tableState") ?? "") is required to fully decode it before parsing with new URLSearchParams(). This pattern allows bundling multiple filter/pagination params as a single search parameter.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
📚 Learning: 2025-08-14T12:13:20.455Z
Learnt from: myftija
Repo: triggerdotdev/trigger.dev PR: 2392
File: packages/cli-v3/src/utilities/gitMeta.ts:195-218
Timestamp: 2025-08-14T12:13:20.455Z
Learning: In the GitMeta schema (packages/core/src/v3/schemas/common.ts), all fields are intentionally optional to handle partial data from various deployment contexts (local, GitHub Actions, GitHub App). Functions like getGitHubAppMeta() are designed to work with missing environment variables rather than validate their presence.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
🧬 Code graph analysis (1)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx (1)
apps/webapp/app/components/primitives/Switch.tsx (1)
  • Switch (64-119)
🔇 Additional comments (2)
apps/webapp/app/v3/environmentVariables/repository.ts (1)

50-55: LGTM for isSecret preprocessing.
Accepts form string payloads while keeping boolean validation intact.

apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts (1)

363-443: Secret flag persistence looks consistent.
The isSecret update happens inside the same transaction as the secret write, which is the right place for it.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@JoanLaRosa
JoanLaRosa force-pushed the feat/make-env-var-secret branch from 3a2939b to d509417 Compare January 29, 2026 15:54
@JoanLaRosa
JoanLaRosa marked this pull request as ready for review January 29, 2026 15:57
coderabbitai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

…ation

Move the secret toggle into the edit form so it submits on Save
instead of firing a separate request immediately. Remove the standalone
makeSecret action/method and include isSecret as an optional field on
the existing editValue flow.
@JoanLaRosa
JoanLaRosa force-pushed the feat/make-env-var-secret branch from d509417 to 8c97d18 Compare August 26, 2026 17:47
@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@JoanLaRosa

JoanLaRosa commented Aug 26, 2026

Copy link
Copy Markdown
Author

⚠️ Prior approval is stale, please re-review.

@matt-aitken your approval was submitted against d509417, which is no longer the head of this branch. I rebased onto latest main and the rebase required manual conflict resolution in three files, so the code you approved is not the code currently on the branch:

  • apps/webapp/app/v3/environmentVariables/repository.ts — kept both lastUpdatedBy (new on main) and isSecret on EditEnvironmentVariableValue.
  • apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts — collapsed main's version/lastUpdatedBy update and my isSecret update into a single environmentVariableValue.update call.
  • .../environment-variables/route.tsx — reconciled conformgetInputProps (main migrated the form API) and dropped an unused import.

New head is 8c97d18. I don't have write access on this repo, so I can't dismiss the old review or hit re-request review myself — could you dismiss it and take another pass? Webapp typecheck shows no new errors from these files and oxfmt/lint/knip pass on push.

devin-ai-integration[bot]

This comment was marked as resolved.

@JoanLaRosa

Copy link
Copy Markdown
Author

Addressed the latest review feedback in da75a16ac:

  • Reset the secret toggle whenever the edit dialog opens, preventing cancelled state from leaking into a later save.
  • Added confirmation before the irreversible non-secret → secret transition.
  • Preserved undefined in the optional isSecret Zod preprocessing rather than coercing it to false.
  • Added the required webapp feature note under .server-changes/.

Validation: focused schema behavior check passed (undefined, true, false), touched files have no typecheck errors, and the push hooks passed formatting, lint, and knip.

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.

2 participants