Fixes a bug where `registerInstance` and
`register{Frontend|Backend}Client` would overwrite each other's data in
the instance service, leading to the bulk update being made with partial
data, often missing SDK version. There's a different issue in the actual
store that causes sdk version and type to be overwritten when it's
updated (because we don't use `setLastSeen` anymore), but I'll handle
that in a different PR.
This PR adds tests for the changes I've made. Additionally, I've made
these semi-related bonus changes:
- In registerInstance, don't expect a partial `IClientApp`. We used to
validate that it was actual a metrics object instead. Instead, update
the signature to expect the actual properties we need from the cilent
metrics schema and set a default for instanceId the way Joi did.
- In `metrics.ts`, use the `ClientMetricsSchema` type in the function
signature, so that the request body is correctly typed in the function
(instead of being `any`).
- Delete two unused properties from the`createApplicationSchema`. They
would get ignored and were never used as far as I can tell. (`appName`
is taken from the URL, and applications don't store `sdkVersion`
information).
- Add `sdkVersion` to `IClientApp` because it's used in instance
service.
I've been very confused about all the weird type shenanigans we do in
the instance service (expecting `IClientApp`, then validating with a
different Joi schema etc). I think this makes it a little bit better and
updates the bits I'm touching, but I'm happy to take input if you
disagree.
https://linear.app/unleash/issue/2-3695/allow-empty-flag-names-to-be-reported-in-bulk-metrics
Accepts metrics with empty flag names in the `/api/client/metrics/bulk`
endpoint.
When testing unknown flags through Edge, which uses the `/bulk`
endpoint, we noticed that there's a slight difference in validation
behavior compared to the regular metrics endpoint. While the regular
endpoint allows empty flag names, this one does not.
We can argue that we don't care about empty flag names in the first
place, which is true, but this inconsistency between the metric
endpoints can be confusing, and it also means that a single empty flag
name evaluation would break metrics being reported for that entire Edge
instance, for example.
This way we still accept it, just like we currently do if we point to
Unleash directly instead of going through Edge.
**Note**: We noticed that, due to the slightly different logic branch,
the bulk metrics endpoint does not report unknown flags. We'll take a
look at this at a later point.
This is primarily to facilitate reading and processing these events in
the payg cloud section of Unleash. We only emit these in one place, so I
added the types in there.
I found this method when running through the environment store that has
0 references. I also can't find any references to it in enterprise and
it's not in the interface. I think it's safe to remove.
## About the changes
When inserting a user with an invalid role id, the user creation will
succeed but there will be no record in the audit log.
The API call returns a 400 misleading you to believe the user was not
created, but it actually was.
This makes the whole user creation transactional, so if something fails,
data will be in the right state.
## Testing
The e2e test was split in 2 scenarios, one with smtp and another one
without.
This test was added, and it was failing before adding the transaction,
because when fetching the users, the user was there, despite having
returned a 400 error in the API call:
80a2e65b6f/src/test/e2e/api/admin/user-admin.e2e.test.ts (L181-L204)
I noticed event search, as it is doing `ILIKE` search, is slow
sometimes. Lets get some statistics about it.
Meanwhile added timers for other interesting queries.
Accepts the new impact metrics into the singleton registry and then does
nothing with them. If the relevant flag is off, the metrics are stripped
from the existing metrics data format and dropped on the floor
#10121 points out that we're using md5 functions still. This PR updates
our migrations to no longer use md5 at all (so if you haven't run the
migrations, you won't get email hashes until you get to the included
migration with this PR). If you've already run the migrations, we'll
drop the existing `email_hash varchar(32)` column and replace it with a
`email_hash TEXT` column.
We're also replacing the md5 function with `encode(sha256(email),
'hex')`. encode has been supported since PG10, sha256 came with PG11.
Do we want an index on the email_hash? I wasn't sure, but if we want to
do lookup we probably should have an index on it (though not a unique
one)
Made a few QoL improvements:
- Don't use default export for class
- Move users store to a feature package (didn't move the interface as it
might be referenced elsewhere)
- Add types for query builders (and ts-expect-error when needed)
**BREAKING CHANGE**: DEFAULT_ENV changed from `default` (should not be
used anymore) to `development`
## About the changes
- Only delete default env if the install is fresh new.
- Consider development the new default. The main consequence of this
change is that the default is no longer considered `type=production`
environment but also for frontend tokens due to this assumption:
724c4b78a2/src/lib/schema/api-token-schema.test.ts (L54-L59)
(I believe this is mostly due to the [support for admin
tokens](https://github.com/Unleash/unleash/pull/10080#discussion_r2126871567))
- `feature_toggle_update_total` metric reports `n/a` in environment and
environment type as it's not environment specific
BREAKING CHANGE: As part of the preparation for a new major (7.0) this
removes /api/admin/projects/{projectId} endpoint. It has been deprecated
since 5.8, and we don't use it anymore in our frontend.
This removes a strategy that was already deprecated, but only for new
installations.
I tested starting with an installation with this strategy being used and
then updating, and I was still able to edit the strategy, so this should
not impact current users.
On a fresh install the strategy is no longer available.
---------
Co-authored-by: Nuno Góis <github@nunogois.com>
BREAKING CHANGE: This removes the
GET /api/admin/projects/{project}/features/{featureName}/variants
PATCH /api/admin/projects/{project}/features/{featureName}/variants
PUT /api/admin/projects/{project}/features/{featureName}/variants
endpoints
Users should move to environment or strategy specific variant methods
rather than feature level variant methods.
If there are two concurrent requests to create or edit change requests,
two separate ones may be created in parallel. The UI does not currently
handle this scenario, and if additional changes are made, they might be
added to a random existing change request—resulting in a messy and
unpredictable state.
This PR adds a unique index to the `change_requests` table
```
on (created_by, project, environment)
WHERE state NOT IN ('Applied', 'Cancelled', 'Rejected', 'Scheduled').
```
In the extremely rare case where such conflicting data already exists in
a database, the migration will automatically cancel one of the
conflicting change requests.
Unleash is being too reactive to events inside Unleash. We should not
update etag if feature is created or tag is added to feature.
This PR adds this condition and adds test for it.
Now we can receive custom metrics, return those for UI and have extra
prometheus endpoint for it.
---------
Co-authored-by: Christopher Kolstad <chriswk@getunleash.io>
Blocks deletion of context fields that are in use and updates the
"active usage" count to exclude use in archived flags.
- Before allowing you to delete a context field, checks if it is in use
by any strategies. If so, returns a 409 error.
- Updates what we count as "in use" to exclude flags that have been
archived.
BREAKING CHANGE: Context fields can no longer be deleted if they are in
use by active (non-archived) flags.
Vitest Pros:
* Automated failing test comments on github PRs
* A nice local UI with incremental testing when changing files (`yarn
test:ui`)
* Also nicely supported in all major IDEs, click to run test works (so
we won't miss what we had with jest).
* Works well with ESM
Vitest Cons:
* The ESBuild transformer vitest uses takes a little longer to transform
than our current SWC/jest setup, however, it is possible to setup SWC as
the transformer for vitest as well (though it only does one transform,
so we're paying ~7-10 seconds instead of ~ 2-3 seconds in transform
phase).
* Exposes how slow our tests are (tongue in cheek here)
https://linear.app/unleash/issue/2-3564/remove-filterexistingflagnames-feature-flag
We're removing the `filterExistingFlagNames` feature flag since we've
decided we want this to be the default behavior.
We don't need to rush to merge it, just in case we need to disable this
for any reason. However it should also be pretty easy to just revert if
needed.
Changes in tests are a bit tricky since they assumed the previous
behavior where we always registered metrics, even for non existing flag
names. `cachedFeatureNames` is also memoized with a TTL of 10s, so the
easiest way to overcome this was to override `cachedFeatureNames` to
return what we expected. As long as they return the same flag names that
we expect, we're able to register their metrics.
Let me know if you can think of a better approach.
Improves handling of constraints in use that have been deleted.
This change implments a few small changes on both the front and the back
end on how we deal with constraints that have been deleted.
The most important change is on the back end, in the
`/constraints/validate` endpoint. We used to throw here if the
constraint couldn't be found, but the only reason we wanted to look for
the constraint in the db was to check for legal values. Now, instead,
we'll allow you to pass a constraint field that doesn't exist in the
database. We'll still check the values against the operator for
validity, we just don't control legal values anymore (because there
aren't any).
On the front end, we improve the handling by showing the deleted context
filed in the dropdown, both when the selector dropdown is closed and
when it is open. However, if you change the context field, we remove the
deleted field from the list. This seems like a sensible tradeoff. Means
you can't select it if you've deselected it.
We're migrating to ESM, which will allow us to import the latest
versions of our dependencies.
Co-Authored-By: Christopher Kolstad <chriswk@getunleash.io>
Add `getProjectLinkTemplates` method to ProjectStore and corresponding
test. Ideally this should be in a read-model, but let's finish link
templates end to end
Adds support for link templates in projects, allowing reusable URL
patterns with placeholders. Includes validation, database changes,
updated API schemas, and tests.
https://linear.app/unleash/issue/2-3406/hold-unknown-flags-in-memory-and-show-them-in-the-ui-somehow
This PR introduces a suggestion for a “unknown flags” feature.
When clients report metrics for flags that don’t exist in Unleash (e.g.
due to typos), we now track a limited set of these unknown flag names
along with the appnames that reported them. The goal is to help users
identify and clean up incorrect flag usage across their apps.
We store up to 10 unknown flag + appName combinations, keeping only the
most recent reports. Data is collected in-memory and flushed
periodically to the DB, with deduplication and merging to ensure we
don’t exceed the cap even across pods.
We were especially careful to make this implementation defensive, as
unknown flags could be reported in very high volumes. Writes are
batched, deduplicated, and hard-capped to avoid DB pressure.
No UI has been added yet — this is backend-only for now and intended as
a step toward better visibility into client misconfigurations.
I would suggest starting with a simple banner that opens a dialog
showing the list of unknown flags and which apps reported them.
<img width="497" alt="image"
src="https://github.com/user-attachments/assets/b7348e0d-0163-4be4-a7f8-c072e8464331"
/>