Skip to content

Make the Cloudinary cloud name a constant, not a secret - #191

Merged
renrenmimi merged 1 commit into
mainfrom
chore/cloud-name-not-a-secret
Sep 7, 2026
Merged

Make the Cloudinary cloud name a constant, not a secret#191
renrenmimi merged 1 commit into
mainfrom
chore/cloud-name-not-a-secret

Conversation

@renrenmimi

Copy link
Copy Markdown
Owner

The cloud name is the first path segment of every image URL the app serves. It is public by construction — anyone who has loaded a single photo already has it — and storing it in Secret Manager protected nothing.

What it did instead

It invented a failure mode. Because it was a secret param, every callable that validates a media URL had to remember secrets: [CLOUDINARY_CLOUD_NAME], and one that forgot would pass CI and throw in production on the first upload.

CI structurally cannot catch that: the emulator drives handlers through .run(), which bypasses secret mounting entirely, and setup.ts set the variable directly — so the tests saw a value the deployed function would not have had. #185's own description flagged this and had to derive the list of eleven bindings by grepping call paths rather than by testing.

The change

All eleven bindings gone. The value lives in platform.ts next to CLOUDINARY_FOLDER, and shared.ts reads it directly instead of reaching into process.env — which also removes the "misconfigured" branch that existed purely to handle a caller arriving without the binding. There is no longer a way to arrive without it.

CLOUDINARY_API_KEY and CLOUDINARY_API_SECRET stay in Secret Manager — those are the credentials, and media.ts keeps binding them. The truthiness check there now covers only those two.

The part that matters beyond tidiness

setup.ts stops setting CLOUDINARY_CLOUD_NAME, and the tests compare against the constant. A test can no longer pass because the environment supplied something production would not have. That is the same shape as the bug in #187, where a test recomputed the implementation's own wrong assumption and passed while every upload failed.

Functions 80/80, build / lint / typecheck:test clean.

Deploy note

This changes the deploy config of eleven functions (removing a secret binding), so they will genuinely redeploy rather than report "no changes detected".

🤖 Generated with Claude Code

Copilot AI lite review requested due to automatic review settings September 6, 2026 22:17
@vercel

vercel Bot commented Sep 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
pet-note Ready Ready Preview Sep 7, 2026 1:53am UTC

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

The cloud name is the first path segment of every image URL the app serves. It
is public by construction — anyone who has loaded a single photo already has
it — and storing it in Secret Manager protected nothing.

What it did instead was invent a failure mode. Because it was a secret param,
every callable that validates a media URL had to remember
`secrets: [CLOUDINARY_CLOUD_NAME]`, and one that forgot would pass CI and throw
in production on the first upload. CI cannot catch that: the emulator drives
handlers through .run(), which bypasses secret mounting entirely, and setup.ts
set the variable directly, so the tests saw a value the deployed function would
not have had. #185's own description flagged this and had to derive the list of
eleven bindings by grepping call paths rather than by testing it.

All eleven bindings are gone. The value lives in platform.ts next to
CLOUDINARY_FOLDER, and shared.ts reads it directly instead of reaching into
process.env — which also removes the "misconfigured" branch that existed only
to handle a caller arriving without the binding. There is no longer a way to
arrive without it.

CLOUDINARY_API_KEY and CLOUDINARY_API_SECRET stay in Secret Manager. Those are
the credentials, and media.ts keeps binding them. The truthiness check there
now covers only those two, since the cloud name cannot be empty.

setup.ts stops setting CLOUDINARY_CLOUD_NAME, and the tests compare against the
constant. That is the part that matters beyond tidiness: a test can no longer
pass because the environment supplied something production would not have.

Functions 80/80, build / lint / typecheck:test clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@renrenmimi
renrenmimi force-pushed the chore/cloud-name-not-a-secret branch from 627fbfd to 239349a Compare September 7, 2026 01:53
@renrenmimi
renrenmimi merged commit 3e89d02 into main Sep 7, 2026
6 checks passed
@renrenmimi
renrenmimi deleted the chore/cloud-name-not-a-secret branch September 7, 2026 01:55
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