Cloud runs two frontend replicas and node-schedule fires on each, so both
would read the same unset marker and every trial user would get the email
twice. A Postgres advisory lock lets one replica run and the other skip;
it lives in the connection rather than the schema, so no migration.
Drops the 3-day reminder, leaving the single notice before billing starts.
Stripe merges metadata on update, so spreading the snapshot read during
the list call re-asserted stale values over anything written since. Send
only the key being claimed.
The claim is not exclusive and the comment no longer says it is: two
replicas can still read the same unset marker. Marking before the send
only keeps a crash mid-send from resending on the next run.
Trials were always Hobby, so a trial user who wanted Startup had to go
through Checkout, which created a second subscription on the same
customer. Seven days later Stripe cancelled the trial sub and the webhook,
matching only on customer id, zeroed serversQuantity and deactivated the
servers of someone who was already paying.
The trial now starts on the plan the user chooses and switching plans
mutates that same subscription, so a customer never holds two.
- startFreeTrial takes a tier; TRIAL_SERVER_LIMIT becomes TRIAL_SERVER_LIMITS
(Hobby 1 server, Startup 3)
- onboarding offers both plans with a trial and a subscribe button
- billing exposes Switch to Startup/Hobby during the trial and hides the
checkout CTAs and server steppers that would create a second subscription
- upgradeSubscription caps the server count to the plan's included servers
while trialing and skips proration, which emitted an orphan invoice
- webhook treats trialing as active instead of disabling servers, and
guards invoices that carry no subscription
- getBillingStatus reports hasPaymentMethod, so the banners stop asking for
a card once one is on file
- new cloud-only daily job emails trial users without a payment method at 3
and 1 days left, deduped through subscription metadata claimed before the
send so concurrent replicas cannot double-send
Review flagged that multi-import collisions were untested. The order the code
implements is the documented one — Infisical: "If two imports carry a secret
with the same name, the value from the bottom-most import wins" — and the
response lists imports in that order, so sequential assignment matches it.
Added a case with two imports defining the same key. Reversing the merge order
in the client fails it, so the test pins the behaviour rather than restating
the implementation.
vault.test.ts: 58 passed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fixes#5413. A secret brought into a folder with "Import Secrets" was reported
as not found. Two reasons, and the first is easy to miss:
The list endpoint takes the flag in **snake_case**. `includeImports` is
silently ignored — the request still returns 200, with `imports` present but
empty — so the imported secret looked like it simply did not exist. Measured
against app.infisical.com with a registered import (confirmed via
GET /api/v1/secret-imports):
expandSecretReferences=true imports[] empty
expandSecretReferences=true&includeImports=true imports[] empty
expandSecretReferences=true&include_imports=true imports[] has the secret
Second, imported secrets never appear in `secrets` — they come back in a
separate `imports` array, one entry per source path, which the client did not
read at all.
Imported entries are merged before the folder's own, so a name defined in both
resolves to the local value, matching how Infisical resolves it.
Also measured, for whoever looks next: `/api/v4/secrets` returns imports with
no flag at all, and single-secret reads (`/raw/{name}`) never see an imported
key — 404 on v3, no such route on v4. So a folder listing is the only way to
reach them.
vault.test.ts: 57 passed. Reverting the fix fails the new merge test.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds a Transfer action on every service page that moves an application,
compose or database to another server without S3: volumes, bind mounts
and deployment logs are streamed through the panel (ssh2/spawn pipe),
file mounts and Traefik config are recreated on the target, the source
is cleaned up and the service is deployed on the target. Failures before
cleanup roll back to the source server.
/etc/docker/daemon.json isn't mounted into the dokploy container, only
docker.sock is, so cat-ing it always failed silently. Read the effective
config over the already-mounted socket instead.
Fixes#5383
An Infisical provider is pinned to one non-recursive `secretPath`, so reading
two folders means two providers, two machine identities and two sets of
credentials to rotate. This lets a reference name the folder instead:
${{vault.my-provider.external/sentry:SENTRY_DSN}}
`<path>:<KEY>` mirrors the HashiCorp client in this directory, which already
documents that exact format. A relative path resolves against the provider's
`secretPath`, a leading slash is absolute, and a ref without a colon keeps its
current meaning — the whole ref is the secret name at the provider's own path.
A dot cannot be the separator here: Infisical accepts dots inside secret names
(`A.B.C` is a valid key), so `provider.a.b.C` cannot be split unambiguously
and would silently break anyone using such a name.
Refs are grouped by resolved path so each path is listed once, and the login
happens once per batch rather than once per path.
Tests cover the bare ref, relative and absolute paths, a provider at `/`,
grouping with a single login, the error naming the path, and a malformed ref.
Previously, upsertRecord matched only by type and name, silently
overwriting any existing record of the same type/name with different
content. This caused data loss when users had multiple records of the
same type (e.g. multiple TXT records for SPF + site verification).
Now upsertRecord also checks the record content/target before deciding
to update. If the content differs, a new record is created alongside
the existing one instead of replacing it.
Affected providers: Cloudflare, Porkbun, Infomaniak, OVH.
Tests updated accordingly.