v26.3.17
v26.3.17
DSYNC_WEBHOOK_LOGS_TTL rejects a value that is not a duration
DSYNC_WEBHOOK_LOGS_TTL summed whichever <number><unit> tokens appeared anywhere in its value, so a typo carrying one was
accepted as a retention rather than reported: 1d garbage kept logs for a day, and typo1h for an hour. The release that added
the setting described this leniency, but it means a mistyped value changes how long logs are kept and says nothing about it.
A value must now be a duration end to end, such as 720h, 30d or 1d 12h. Anything else falls back to the seven-day default
and logs a warning, which is what an unrecognized value has always done. Unset still means seven days and an empty value still
keeps logs indefinitely, and now says so in a warning of its own, because a store with no expiry grows for as long as the
deployment runs.
Breaking: a value that carries a duration inside something else kept logs for that duration and now keeps them for seven days.
1d garbage and typo1h are the shapes this catches. Check the value before upgrading if you set this; spaced durations such as
1d 12h are unaffected and still mean what they say.
SSO_TRACES_TTL and DSYNC_WEBHOOK_LOGS_TTL now resolve their retention through one shared function, so a duration, an empty
value and a typo mean the same thing in both.
SSO_TRACES_TTL now applies in both directions
SSO_TRACES_TTL reached the trace store, which expires the records, but a second cleanup inside Polis deleted anything older than
a hardcoded week and never read the setting. Whichever of the two was shorter won, so a value below seven days took effect and a
value above it was silently capped at seven. The direction people set this for -- keeping traces long enough to investigate a
failure reported weeks later -- was the one that did nothing.
That cleanup is gone and retention is the store's own expiry, so the setting now means what it says. Leaving it unset still keeps traces for seven days.
SSO_TRACES_TTL still takes a number of hours, and now also takes a duration such as 720h or 30d, matching
DSYNC_WEBHOOK_LOGS_TTL. Set it to an empty value to keep traces indefinitely. A value that is not a duration end to end falls
back to the seven-day default and logs a warning, so a typo never silently changes retention.
Setting it to an empty value now survives option normalization as well. The package filled an unset trace TTL with its seven-day default using a falsy check, which turned the zero that means indefinite back into seven days, so there was no way to ask for it at all.
Breaking: a deployment that declares SSO_TRACES_TTL with an empty value kept traces for seven days and now keeps them
indefinitely. If you set the variable but leave it blank, either remove it or give it a retention such as 168h, otherwise the
trace table grows for as long as the deployment runs. Polis logs a warning at startup whenever traces are kept indefinitely.
Bulk deletes now remove every record, not just the first page
Deleting all SSO connections for a tenant and product removed only as many connections as a single database read returns, which is
capped by DB_PAGE_LIMIT and defaults to 50. The call still reported success, so a tenant with more connections than that was
left with working SSO connections after what looked like a complete deprovision. Deleting traces for a product had the same
problem and stopped after 50 traces.
Both now page through every matching record. If you have deprovisioned a tenant with more than DB_PAGE_LIMIT SSO connections,
run the delete again to clear whatever was left behind, or list the connections for that tenant and product to check.
On MongoDB, paged reads could also repeat some records and skip others when they shared a creation time, which bulk imports make common. Each record now appears exactly once.
Find a customer's SSO connections and directories by tenant
The Admin Portal listed every SSO connection and every directory a page at a time with no way to ask for one customer's, so finding them meant paging until they appeared, and finding both meant doing it twice.
Both lists now take a tenant and a product and answer with that customer's records. A tenant in either list is also a link to the same tenant on the other, so a connection leads to the directories beside it and back.
Both terms are needed and each has to match what was stored: records are indexed by tenant and product together, so this is a
lookup rather than a search. The same two parameters work on GET /api/admin/connections and GET /api/admin/directory-sync,
which answer with the customer's records in full and no pagination.
Reading a customer's directories by tenant and product returned only as many as a single database read yields, which
DB_PAGE_LIMIT caps and defaults to 50, so a customer with more directories than that saw a short list with nothing to indicate
records were missing. It now reads through to the end, which also affects GET /api/v1/dsync and the setup link that lists a
customer's directories.
Find a directory's users and groups by email or name
The Admin Portal listed a directory's users and groups a page at a time with no way to ask for one of them, so answering whether a person had been provisioned meant paging through the directory until their row appeared.
Both lists now take a term and answer with the matching record. The same parameters work on
GET /api/admin/directory-sync/{directoryId}/users, which takes email, and
GET /api/admin/directory-sync/{directoryId}/groups, which takes name. Either answers with the record itself and without
pagination, since a directory holds one user per address and one group per name.
The term has to match what the identity provider sent, in full: users are indexed by directory and email together and groups by directory and name, so this is a lookup rather than a search. A partial address or name is a different key and finds nothing, which the field says above the list.
A user whose email address changed after they were provisioned, or a group that was renamed, is still indexed under the value it was created with, so the lookup answers to that value and not to the current one. Those records remain in the unfiltered list.
SCIM user and group listings now page past the first set of records
Listing directory users or groups over SCIM reported the first page as the whole directory, so an identity provider reading the
list stopped after DB_PAGE_LIMIT records and never saw the rest. Group listings ignored startIndex and count altogether and
answered every request with the same records.
Both endpoints now honour startIndex and count and report a totalResults that keeps the caller paging until the directory is
exhausted. totalResults is a lower bound while more records remain and becomes exact on the final page, so a client that pages
until it has seen totalResults records now reads the whole directory. If a directory looked short in your identity provider, run
a synchronisation again to pick up the records that were never returned.