Lakekeeper+ Release Notes¶
v0.14.1 (2026-10-16)¶
Based on Lakekeeper OSS v0.14.1.
Bug Fixes¶
- UI paths. The UI no longer serves a file for a path that contains
ui/a second time. Such a path now returns404. - Security updates of dependencies.
rustls,quinn-protoandxxhash-rustare updated to fix security advisories RUSTSEC-2026-0338 to -0342, RUSTSEC-2026-0346 to -0349 and GHSA-6g2r-675j-hx59.
Upstream Lakekeeper changes (bump to v0.14.1)¶
All changes are in the Lakekeeper release notes. The most important ones for Lakekeeper Plus:
- Security: S3 remote signing signs only what it knows. Unknown query parameters and headers are refused, and so are writes that use an encryption key other than the warehouse's (lakekeeper#2102).
- Remote signing with Iceberg 1.12 or later. Batch deletes and repeated deletes, for example in
expire_snapshotsorremove_orphan_files, no longer fail with403 SignatureDoesNotMatch(lakekeeper#2124, lakekeeper#2104). - Concurrent commits to one table that block each other in the database return a
409error, which clients retry, instead of503. A commit that removes the last branch or tag of a table is now kept (lakekeeper#2117).
v0.14.0 (2026-10-08)¶
Based on Lakekeeper OSS v0.14.0.
Highlights¶
- Cedar: grants decide access. Predefined policies turn the grants you give in the console or through the Grants API into access, so you can hand out permissions without changing a policy file. Each project and warehouse chooses which predefined policies apply. See Predefined policies.
- Cedar: policies per project and warehouse. Each project and warehouse can keep its own Cedar policies, managed in the console or through the API. If a policy locks everyone out, an operator can repair it with break-glass. See Break-Glass.
- Cedar: roles and governance tags. Roles can be created and managed in Lakekeeper, and policies can decide access by governance tags. See Tag-Based Access Control.
Features¶
- Grants in policies. Each resource carries what the principal holds on it as
principal_privileges:directfor grants on the resource itself,inheritedfor grants above it. For example:resource.principal_privileges.direct.select. Grant actions carry the privilege being granted ascontext.privilege. With externally managed users and roles, give grants to users: your entity file holds role membership, so a grant to a role does not apply. - Predefined policies. They are on by default;
LAKEKEEPER__CEDAR__PREDEFINED_POLICIES_ENABLED=falseswitches all of them off. A project or warehouse can switch single policies on or off. A policy that a later release adds starts switched off where you have already chosen. Withinclude-policy=true, the listing also returns each policy's rule. Policy listings say incan-writeandcan-togglewhether you may change them. - Policies per project and warehouse. Manage them in the console or through the
…/policiesendpoints. A change is checked as a whole and applied in one transaction.dry-runpreviews it,if-scope-versionprotects against concurrent edits, andreplace: truereplaces all policies of the scope. A scope holds up to 1000 policies (LAKEKEEPER__CEDAR__MAX_POLICIES_PER_SCOPE). - Break-glass. With the header
x-break-glass: <reason>, an operator is judged by the server's policies alone and can repair a project's or warehouse's policies. It opens policy administration only, never data, and every use is audited with its reason. Thebreak-glass-statusendpoint tells you whether it is open to you. Instance admins must send the header to write a scope's stored policies. - New privileges for separation of duties.
manage_policiesreads and writes a scope's policies, andread_policiesonly reads them.read_grantsshows who holds what on an object and below it; this reveals that an object exists, even where a policy hides it.manage_tagstags objects; attaching a tag also needsapplyormanageon the tag, so hand outapplycarefully when policies decide access by tags. None of these privileges gives access to data by itself, but amanage_policiesholder can write a policy that does, somanage_policiesis never part ofmanage.pass_grantspasses on onlydescribe,select,write,createand, on a tag,apply. - Governance tags in policies. Creating, applying, removing, reading, changing and deleting tags are Cedar actions. Each warehouse, namespace, table, view and generic table carries its effective governance tags, including inherited ones, as
governance_tags. For example:resource.governance_tags.hasTag("pii"). Keys match the tag name exactly, including case. Column tags are not included. - Grant administration for whole subtrees. Listing and revoking all grants under a warehouse or namespace, and listing everything one user or role holds in a project, are Cedar actions of their own. By default,
manage_grantsandread_grantsholders may list, andmanage_grantsholders may revoke. Policies see what a request covers incontext.subtree. The decision is made once, on the named warehouse or namespace; aforbidon objects below does not narrow it. A bulk revoke cannot be undone. - Roles under Cedar. Roles managed in Lakekeeper (provider
lakekeeper) can be created, renamed, given members and deleted, in the console and through the API. By default, projectmanage_grantsholders manage them, anddescribe,create,manageandmanage_grantsholders can read them. Roles from identity and role providers can be deleted too, for example after their group was removed from the directory. A role that still holds grants needsforce=true. - Moves are checked at both ends. Moving a table, view or generic table into another namespace checks
MoveTable,MoveVieworMoveGenericTableon the object andAcceptMovedTabularInNamespaceon the new namespace. Policies see the new namespace incontext.destinationand the old one incontext.source. New predefined policies allow moves, including moving and renaming namespaces:manageandmanage_grantson the object to move it out, andcreateormanageon the new namespace or warehouse to move it in. - Server grants. Grants on the server go to users; a grant to a role is refused with
400 ServerGrantToRole. No predefined policy decides server actions: load the five server-grantpermits from the "Server Actions" section of the schema to make server grants take effect. See Server grants. - Server policy check. When the server loads its policies, it refuses a policy that would stop fewer users at a server action, and the log shows the fix. The check does not run when users and roles are managed externally.
- Batch checks name the deciding policies. Under Cedar, each result of
POST /management/v1/action/batch-checklists the policies that decided it indetermined-by. - Server policy endpoints renamed.
policy-sourcesandpolicy-listare nowserver-policy-sourcesandserver-policy-list. The old paths still work but are deprecated. Each source now reports itstier. - Console v0.23.0. Each project's and warehouse's Cedar policies and predefined policies can be managed in the console. With Cedar, grants under a warehouse or namespace can be listed and revoked in bulk. On a table's Tasks tab, snapshot expiration and orphan-file removal each have "Run now" and settings buttons. The console also includes everything in the Lakekeeper console v0.26.0.
- Console settings.
LAKEKEEPER__UI__STORAGE_PROVIDERS_ORDERandLAKEKEEPER__UI__STORAGE_PROVIDERS_HIDDENorder and hide the storage types offered when adding a warehouse.LAKEKEEPER__UI__SUPPORT_DOCS_URL,LAKEKEEPER__UI__SUPPORT_ISSUE_URLandLAKEKEEPER__UI__SUPPORT_CONTACT_URLset the links of the help menu. - Admission gate metrics.
lakekeeper_admission_enforce_call_duration_seconds,lakekeeper_admission_enforce_decisions_totalandlakekeeper_admission_enforce_fail_closed_totalshow how the gate performs. Its cache reports ascache_type="admission_enforce". - New commands.
openfga reconcilerepairs OpenFGA's hierarchy tuples from the catalog; OpenFGA users can now run the reconcile recommended in 0.13.6.reopen-bootstrap --yesallows bootstrapping again, for example after a misconfigured first bootstrap. It changes no data and no policies, but until bootstrap runs again, the next authenticated caller of/management/v1/bootstrapbecomes the initial admin.
Bug Fixes¶
- Role providers: stored roles are used only when every unreachable provider has synced the user. Before, a policy that forbids a group from a missing provider could be skipped.
- Role providers: fewer directory calls. A user's groups are fetched once and reused in every project until they are due for a sync. A user without groups keeps working while the provider is down.
- Persisted token roles apply in every project. While a user is active, their token roles are stored again at most every two minutes. A decision about a user who has made no request in the project, such as a DEFINER view's owner, uses their newest stored roles from any project.
- Cedar: the project list decides each project with the caller's roles in that project. Acting as a role lists only that role's project.
- Looking up another user's groups writes nothing. Permission checks about another user and DEFINER views no longer create users or roles. A caller who may not make such a check is refused before that user's groups are looked up.
- Directory role providers resolve only the users of their identity provider. Before, with several identity providers, a user could receive the groups of another provider's user with the same subject.
- Roles named after an identity provider that supplies no roles can be renamed and deleted.
managed-role-providersinGET /management/v1/infolists only the configured role providers. - Snapshot expiration deletes only files inside the table location. Other files are left in place and counted in the task result's
skipped-outside-table-location-count, so tables that write data outside their location, for example withwrite.data.path, keep their expired data files. A snapshot history that loops no longer hangs expiration, and a branch or tag moved onto an expiring snapshot during expiration is kept. - Commands behave as in Lakekeeper.
healthcheckwithout flags checks/health(before, it checked nothing),wait-for-dbreads the migration state from the primary database,migrateruns the steps after the migration, andservereports thelakekeeper_catalog_pg_pool_*metrics. - Cedar: a request the authorizer cannot build returns
500instead of503. Retrying does not help; the details are in the server log.
Breaking Changes¶
- Cedar: server actions use the user's groups. Server actions are the few actions on the server itself, such as creating projects and managing users. At server actions, policies see the user's groups from Entra ID, LDAP, Okta, token claims and admission gates, and these groups are the same in every project. Roles managed in Lakekeeper belong to one project, so they do not count at server actions. In server-action policies, name a group with
principal.project_roles.contains({provider_id: "ldap", source_id: "<group>"})instead of aLakekeeper::Role::"…"id. Send server requests withoutx-assume-role, because Lakekeeper denies server actions to requests withx-assume-role. See Role scope at server actions. - Cedar: new action groups for reading policies and for checks about other users. Reading the server's policy sources is in
ServerCedarPolicyActionsandCedarPolicyReadActions. Checking what another user or role may do (Introspect<X>Authorization) is in<X>GrantActionsandGrantReadActions. If your policies allow these actions throughServerActions,<X>Actions,<X>ModifyActionsorRoleActions, name the new groups. - Cedar: allow reading role assignments on the project.
ReadUserRoleAssignmentsis now decided on the project and is in no action group. To let users read the role assignments of other users, permitReadUserRoleAssignmentson the project in your own policies, or grant these usersdescribe,create,manageormanage_grantson the project. A policy that namesReadUserRoleAssignmentson the server stops the server from starting. - Cedar: requests are decided in the project of their resources. A catalog request without
x-project-iduses the project of its warehouse, so Iceberg clients need nox-project-idheader. A management request withoutx-project-iduses the default project. Lakekeeper refuses a request whosex-project-idnames a different project than its resources. With more than one project, make sure that management clients send thex-project-idof the resources they manage. - Cedar: moves into another namespace have their own actions. Moving a table, view or generic table into another namespace needs
MoveTable,MoveVieworMoveGenericTableon the object andAcceptMovedTabularInNamespaceon the new namespace, in addition to the rename and create actions. No action group includes these four actions, so name them in your policies. Renames inside one namespace need no change. - Cedar: three requests check one more action. Make sure your policies allow the new action:
- The project list shows the projects where
IncludeProjectInListis allowed. Before, the project list checkedGetProjectMetadata. - Registering a table also checks
GetNamespaceMetadataon the namespace. - Cancelling a soft-deletion task also checks
UndropTable,UndropVieworUndropGenericTable, because cancelling the task restores the object.
- The project list shows the projects where
- Persisted token roles follow the newest token. With
LAKEKEEPER__ROLE_PROVIDER_CHAIN__PERSIST_TOKEN_ROLES=true, Lakekeeper replaces a user's stored token roles with the roles of their newest token, also when the newest token carries no roles. Entra ID leaves out thegroupsclaim for users in more than 200 groups, so give these users their groups through the Entra ID role provider before you upgrade. - Check your configuration before you upgrade. The server checks more settings at startup and stops with a message that names the setting:
LAKEKEEPER__AUTHZ_BACKENDmust beallowall,openfgaorcedar. Other values, such as a typo, used to start the server without authorization.- An authenticator must be configured, such as OpenID or Kubernetes authentication. To run without authentication, set
LAKEKEEPER__INSECURE_ALLOW_UNAUTHENTICATED=true. - With Cedar and users from two or more identity providers, every LDAP, Entra ID and Okta role provider must set
idp_ids. Kubernetes authentication counts as an identity provider. Every entry inidp_idsmust name an identity provider that the server authenticates. - An admission gate authenticates to your endpoint with
headers. Theauthsetting is removed, so the gate never sends the caller's token. The gate configuration must not contain unknown keys, and itsidp_idmust name an identity provider that the server authenticates.
- Audit log format. Existing parsers of the audit log must be updated. See Audit log format below.
Upgrade Notes¶
- Plan downtime and back up the database. Stop all 0.13 servers; with Helm, scale the deployment to zero before
helm upgrade. With OpenFGA, removeLAKEKEEPER__OPENFGA__AUTHORIZATION_MODEL_VERSION. Runmigrateto completion, then start 0.14. The migration can take several minutes on large catalogs. First run the query from "Tables or views that would share a location stop the migration" in the Lakekeeper upgrade notes. Afterwards, 0.13 servers cannot run against the database; to go back, restore the backup. - Grants decide access as soon as they are made. The predefined policies are on by default. To choose them per project or warehouse before they apply, start with
LAKEKEEPER__CEDAR__PREDEFINED_POLICIES_ENABLED=false, switch off what you don't want in each scope, then set it back totrue. - Bulk revoke is on by default.
manage_grantsholders can revoke all grants under a warehouse or namespace, their own included, and a revoke cannot be undone; break-glass does not restore grants. Switch offpredefined-grants-warehouse-grant-admin-subtree-revokeandpredefined-grants-namespace-grant-admin-subtree-revokewhere you don't want this. - Review policies that allow role actions. With Cedar, version 0.13 refused to create or delete roles, whatever the policies allowed. Version 0.14 follows the policies: a policy that allows
CreateRolelets its holder create roles, and a policy that allowsDeleteRole, also throughRoleActionsor through all actions, lets its holder delete roles, including roles from Entra ID, LDAP and Okta. - Directory outages: let service accounts make a request in a project now and then. While an LDAP, Entra ID or Okta directory is down, Lakekeeper uses the groups it stored at the user's own requests in a project. A user who has never made a request in a project, for example a provisioning bot, gets an error while the directory is down, and so does a query on a DEFINER view that this user owns.
- OPA bridge: if you use it, deploy its policies from this release together with the server. Renames into another schema now also check
moveandaccept_moved_tabular.
Upstream Lakekeeper changes (up to Lakekeeper v0.14.0)¶
This release includes Lakekeeper v0.13.6 and v0.14.0. See the Lakekeeper release notes for all changes. Most important for Plus:
- Grants API, governance tags, and moving and renaming namespaces (lakekeeper#1945, lakekeeper#1914, lakekeeper#1950).
- Storage validation, with warnings for STACKIT buckets that other credentials groups can reach and for CORS settings that block the console (lakekeeper#1936, lakekeeper#2050, lakekeeper#2049).
- STACKIT storage type with data platform storage, and Alibaba Cloud OSS (lakekeeper#1978, lakekeeper#2045, lakekeeper#1894).
- Audit log format changes, listed in full under Audit log format below.
- Required token claims, and stricter OpenID settings that can stop the server from starting (lakekeeper#2001).
- Task queue renamed. Rename
LAKEKEEPER__TASK_TABULAR_EXPIRATION_WORKERStoLAKEKEEPER__TASK_SOFT_DELETION_WORKERSbefore you upgrade; the old name stops the server from starting (lakekeeper#1881). - Requests may be up to 32 MiB by default (lakekeeper#1974).
- Role members cache removed. The
LAKEKEEPER__CACHE__ROLE_MEMBERS__*settings have no effect (lakekeeper#2072). - Catalog requests without
x-project-iduse their warehouse's project, and token roles work without a project. Under Cedar, token and admission-gate roles are in every project'sprincipal.project_roles(lakekeeper#2069, lakekeeper#2071). - OpenFGA:
migrateinstalls model v4.13. Revoking needsmanage_grants. Moving a table, view or generic table into another namespace needsmanage_grantsandmodifyon it. Moves and managed-access changes are not possible under an assumed role. Tools that query OpenFGA directly must use the new_effectiverelations, such asselect_effective(lakekeeper#1991, lakekeeper#2029, lakekeeper#2095). - Cancelling a soft-deletion task needs
undropwith every authorizer (lakekeeper#2095). - Batch check:
update_storage_credentialis removed and returns422; checkupdate_storageinstead (lakekeeper#1936). - Smaller changes that can affect clients: reusing an
Idempotency-Keyfor a different operation returns400,referenced-bynames at most 10 views by default, tables can no longer setwrite.object-storage.pathorwrite.folder-storage.path, and unreachable storage fails with412 StorageProbeTimeout(lakekeeper#1959, lakekeeper#1980, lakekeeper#2044, lakekeeper#2047). - All fixes of Lakekeeper v0.13.6, which Plus v0.13.6 did not include yet.
Audit log format¶
Lakekeeper Plus writes the same audit log as Lakekeeper, so this section lists the audit log changes of Lakekeeper v0.14.0 together with those of Lakekeeper Plus.
Breaking changes — an existing parser must be updated:
-
A field is absent when it has no value, and an empty list or map is written out. Nothing in an audit record is
null.A field the request did not supply is left out. A policy factor without a name, for example, has no
namekey instead of"name": null.An empty list or map is a value and is always written once an action can carry it:
before {"action_name": "commit"} after {"action_name": "commit", "updated_properties": {}, "removed_properties": [], "target_refs": [], "update_kinds": []}This applies to
properties,updated_properties,removed_properties,source,destination,target_refsandupdate_kindsin an action, and toauthorizations[].determined_byanderror.stack. A flag such asforce,purgeorrecursiveis also always written, astrueorfalse.What to do: read "none" from an empty value, not from a missing key. Keys that are genuinely optional, such as a name or an id, still need a presence check.
-
Authorization records always carry
actionsandentitiesas lists. The singularactionandentityfields are gone.before "action": {…} or "actions": [{…}, {…}] after "actions": [{…}] before .entity.namespace .action.action_name after .entities[0].namespace .actions[0].action_nameEach entry of
authorizations[]still carries a singularactionandentity.What to do: read
actionsandentitiesas lists, and iterate: a record can carry more than one. -
A
contextvalue has its own JSON type. It is no longer always a string.before "force": "true" "dry_run": "true" "writes": "2" after "force": true "dry_run": false "writes": 2- Booleans:
force,purge,recursive,dry_runandallow_partialin an action, andself_provisioningandself_readincontext. - Numbers:
writesanddeletes. - Principals:
principalsonapply_grantsandprincipalonread_subtree_grantsandrevoke_subtree_grantsare{"user": …}or{"role": …}, the formcontext.principalhas on grant records. A subtree request states withprincipal_scope(everyorone) whether it names one principal;principalis present only forone. - Strings, lists and maps keep their type.
Lakekeeper Plus adds
contextkeys that hold an object, such asscope_changesandappliedonapply_cedar_policies.schema-plus.jsongives the object's definition.What to do: compare a flag with
true, not with"true". Read each key's type from the schema. - Booleans:
-
The entries of
authorizations[].determined_byhave the shape the management API returns from a permission check, and there are two new kinds.before {"Policy": {"policy_id": "p-42", "effect": {"Permit": []}, "source": "cedar"}} after {"type": "policy", "policy-id": "p-42", "effect": "permit", "source": "cedar"}- The kind is in
type. Field names are kebab-case, as in the API.effectispermitorforbid. {"type": "system-authority"}: a built-in authority, not a configured policy, decided the allow. It may carrysourceandreason.{"type": "admission-gate"}: an admission gate would refuse the user. It carriesgate, andcheckwhen the gate names one.
What to do: switch on
type. The same code can parse these entries and a/checkresponse. - The kind is in
-
A request that names nothing to check records empty lists. The made-up
unknownentry is gone.A batch check with
checks: [], and a transaction commit with no table changes, recorded oneauthorizationsentry withentity_typeunknown, and for the commitaction_nameunknowntoo.before "authorizations": [{"action": {"action_name": "unknown"}, "entity": {"entity_type": "unknown"}, …}] after "actions": [], "entities": [], "authorizations": []decisionstill carries the outcome.What to do: stop matching
unknowninentity_typeandaction_name, and handle an emptyauthorizationslist. -
Every key and every value this log names itself is spelled
snake_case, andfailure_reasonis a plain string.Keys that carried a hyphen now carry an underscore:
- in an
entity:generic_table,generic_table_id,namespace_id,project_id,role_id,role_provider_id,role_source_id,server_id,table_id,table_location,tag_definition_id,task_id,user_id,view_id,warehouse_id - in an action:
allow_partial,created_before,dry_run,removed_properties,target_refs,update_kinds,updated_properties - in an authorization record's
context:invoked_by,self_provisioning,self_read - on an
authorizations[]entry:for_principal
Values:
actor_type before assumed-role after assumed_role before lakekeeper-internal after lakekeeper_internal failure_reason before {"ActionForbidden": []} after "action_forbidden"Every
failure_reasonvalue follows the same pattern:action_forbidden,resource_not_found,cannot_see_resource,internal_authorization_error,internal_catalog_error,invalid_request_data.Three sets keep the spelling of the vocabulary they come from:
entity_typeandresource_type(generic-table,tag-definition, as in the management API) andupdate_kinds(Iceberg's update names, such asadd-schema). The objects indetermined_bykeep the management API's field names,policy-idincluded.What to do: rename these keys and values in every query. A query on the old spelling matches nothing and raises no error, so check for the new names explicitly. In
jq,.failure_reason | keys[0]becomes.failure_reason. - in an
-
A role on a record carries its
provider_idandsource_idnext to its id.provider_idis always shown;LAKEKEEPER__AUDIT__TRACING__INCLUDE_ROLE_SOURCE_ID=falseleavessource_idout.before {"role": "1f7b…"} after {"role": "1f7b…", "provider_id": "corporate-ldap", "source_id": "engineering"}This applies wherever a role is named:
authorizations[].for_principal,context.principalongrant_createdandgrant_revoked,principalsonapply_grants, andprincipalonread_subtree_grantsandrevoke_subtree_grants. Both fields are absent when the role no longer exists or could not be looked up. With the setting off,source_idis absent everywhere, including onactor.assumed_role, which carries it otherwise.What to do: correlate on the role's id. Read
provider_idandsource_idas optional on a role a record names, andsource_idas optional onactor.assumed_role. Some providers let a source id be a free-form name, so it might hold personal data; turn the setting off if that matters for your log. -
Renaming a table, view or generic table into another namespace is recorded as
move, notrename, and namespaces have a new actionaccept_moved_tabular.renameTable, renameView, renameGenericTable into another namespace before rename after move destination namespace accept_moved_tabular sourceThe record of such a rename names
moveon the renamed entity, refused or allowed, on replays as well.destinationholds the path of the destination namespace; the entity's new name is not part of it, unlike for a namespacemove, wheredestinationis the full new path. A rename within one namespace is still recorded asrename. Whether the namespace changes is decided on the paths in the request, ignoring upper and lower case of ASCII letters: two paths that differ only in the case of a non-ASCII letter are recorded asmove.accept_moved_tabularis the check on the destination namespace.sourceholds the path of the namespace the entity is moved from. It appears in records of permission checks that name it, such as/management/v1/action/batch-check.The record of cancelling soft-deletion tasks is unchanged: it still names
control_tasks. Cancelling such a task now also requiresundropon its table, view or generic table, and a refusal is recorded as a deniedcontrol_tasks.What to do: if you match table, view or generic-table renames on
rename, matchmoveas well. -
context.rolesonresolve_rolesrecords withoutcome: "roles_resolved"lists role objects instead of strings.before "roles": ["corporate-ldap~engineering", "oidc~viewers"] after "roles": [{"role": "1f7b…", "provider_id": "corporate-ldap", "source_id": "engineering"}, {"provider_id": "oidc", "source_id": "viewers"}]Each object has the keys Lakekeeper's records name a role with.
roleis the role's catalog id, absent for a role without a catalog row for this answer: token roles, and roles resolved above projects.source_idis absent whenLAKEKEEPER__AUDIT__TRACING__INCLUDE_ROLE_SOURCE_ID=false. The list stays ordered by provider and source id.What to do: read each entry of
rolesas an object. To rebuild the old string, joinprovider_idandsource_idwith~.
Additions — an existing parser keeps working:
-
Authorization records carry three new optional fields about the request:
user_agent,break_glassandidempotency_key.user_agent: the request'sUser-Agentheader, as sent and unverified.break_glass: the reason the caller stated in thex-break-glassheader, as sent and unverified.idempotency_key: the request'sIdempotency-Key.
Each is absent when the request did not send it.
What to do: nothing. Treat
user_agentandbreak_glassas claims, never as identity. -
Three more operations record the override that makes them destructive.
role delete force revokes the grants the role still holds warehouse delete force deletes a protected warehouse and everything in it generic-table drop force skips the warehouse's soft-deletion window purge deletes the data filesThey use the same keys as namespace delete, table drop and view drop. The key is present whichever way the flag went.
What to do: if you alert on destructive operations, include these three.
"force": trueis the forced form. -
Three new kinds of audit record: grant changes, admission decisions and idempotent replays.
operation: "grant_created"and"grant_revoked": one record per grant the backend reports as applied, withoutcome: "success"andcontextprincipal,privilege,resource_type, andresource_idandwarehouse_idwhere they apply.operation: "admission_decided": a request an admission gate refused.outcomeisforbiddenorunavailable;contextcarriesgate,status,error_type,message,error_id, anddenied_bywhen the gate named a rule.record_type: "replay": a request answered from an idempotency record without being executed. It carries theactionsandentitiesthe request named and theidempotency_keythat matched, and nodecision.
What to do: nothing, unless you want these records. Select them by
operationor byrecord_type. -
Records can carry the email of the users they name. Off by default;
LAKEKEEPER__AUDIT__TRACING__INCLUDE_USER_EMAIL=trueturns it on.actor.email the principal's email, for principal and assumed_role actors authorizations[].for_principal.email the user's email, for a user subject actions[].principals[].email the user's email, for a user an apply_grants request names actions[].principal.email the user's email, when a subtree grant request names one user context.principal.email the recipient's email, on grant_created and grant_revokedEach is best-effort: absent when the email is not known, never
null. Roles,anonymousandlakekeeper_internalactors never carry one. An email is metadata, not identity: emails are not unique and can change.What to do: correlate on
principal,userandrole, never onemail. If you enable the setting, treat the log as holding personal data: an email stays in the log after the user is deleted. -
Audit records carry four new top-level fields:
record_type,emitters,time, andrequest_idwhen a request caused the record."record_type": "authorization", "emitters": {"lakekeeper": "1.0"}, "request_id": "019684ff-…", "time": "2026-03-14T09:26:53.589793Z"record_typenames the record's shape:authorization,replayoroperation.emittersnames every product that contributed to the record. Each key is a product name, each value theMAJOR.MINORversion of what that product contributes. Records that Lakekeeper Plus writes itself, such asresolve_roles, carry"emitters": {"lakekeeper_plus": "1.0"}. An authorization record also has the keylakekeeper_pluswhen it carries one of Lakekeeper Plus's action names orcontextkeys.request_idis the request that caused the record: the value of thex-request-idresponse header, as sent by the caller or generated by Lakekeeper. It is absent from an operation record no request caused, such as the role-provider recordsresolve_roles,ldap_resolve_rolesandcached_role_provider.timeis when the event happened, in UTC, as RFC 3339 with microseconds.
audit_formatgoverns the record's overall shape. A product's value inemittersgoverns what that product contributes. The two are equal on a record only Lakekeeper produced; do not rely on that.What to do: route on
record_type. Read a product's version from its key:.emitters.lakekeeperfor Lakekeeper,.emitters.lakekeeper_plusfor Lakekeeper Plus. Correlate records with a request throughrequest_id, and order them bytime. -
A new record:
operation: "admission_enforce_check"withoutcome: "role_withheld".The external-enforce gate writes it when the control plane refuses one role but still admits the request.
contextcarriesgate,check,roleandcache_ttl_secs.rolenames the admission role byprovider_idandsource_id, as other records name a role;source_idis absent whenLAKEKEEPER__AUDIT__TRACING__INCLUDE_ROLE_SOURCE_ID=false. The gate caches each answer, so there is one record per answer, not per request.What to do: nothing, unless you want to see withheld roles. Join it with Lakekeeper's
admission_decidedrecords onactororrequest_id. -
Authorization records of Cedar policy requests carry what the request asked to change and how it ended.
New
contextkeys:changesontoggle_predefined_policy: the predefined-policy switches the request asked for, as{"changes": [{"id": …, "enabled": …}], "truncated": …}.- On
apply_cedar_policies: dry_run:truewhen the call only reports what it would do.break_glass: the reason the caller stated, when it stated one.scope_changes: the writes and deletes the request asked for, withwrites,deletes,replace,namesandtruncated.applied: what the apply left behind, withcreated,updated,deleted,deleted_names,truncatedandscope-version.apply_outcome:refusedorfailed, absent when the apply went through.apply_errorsays why.
A list is cut at a fixed length, and
truncatedistruewhen it was.What to do: nothing, unless you audit policy changes. Check
truncatedbefore treating a list as complete.
Also worth knowing — the format itself did not change:
-
Audit records are emitted on the fixed
tracingtargetlakekeeper::audit.A log filter naming
lakekeeper::service::events::backends::audit,lakekeeper::service::admissionor a prefix of either belowlakekeepermatches no audit record. The server warns at start-up when it finds such a filter.What to do: select audit records with
RUST_LOG=warn,lakekeeper::audit=info, or suppress them withRUST_LOG=info,lakekeeper::audit=warn. -
The audit log has published JSON Schemas:
audit/schema.jsonfor Lakekeeper andaudit/schema-plus.jsonfor Lakekeeper Plus, in the documentation, linked from the "Audit Log Schema" page.- Point a validator at the document to check a whole record. Its root,
AuditRecord, requiresevent_source,audit_formatandrecord_typeand selects the shape byrecord_type:AuthorizationRecord,ReplayRecordorOperationRecord. - Every field and key is a property with its type and description.
ActionRecordlists, peraction_name, the keys that action carries. - A value set the log may extend lists its values under
x-audit-values, so a validator accepts a value a later release adds. The closed setsdecision,privilege_scope,root_leveland a policy'seffectuseenum. schema-plus.jsonlists Lakekeeper Plus'soperationandoutcomevalues, thecontextof each of its records, thecontextkeys it adds to authorization records, and its action names. A record whoseemittershas the keylakekeeper_plusis governed by both schemas.
What to do: nothing. Validate with both schemas, or generate a parser from them.
- Point a validator at the document to check a whole record. Its root,
Records from v0.14.0 carry audit_format 1.0 (the first version). Records from v0.14.0 that Lakekeeper Plus contributes to carry emitters.lakekeeper_plus 1.0 (the first version).
v0.13.7 (2026-10-16)¶
Based on Lakekeeper OSS v0.13.7.
Bug Fixes¶
- Security: snapshot expiration deletes only files inside the table location. It runs with the warehouse's storage credentials and follows references in table metadata that clients write. A principal that can commit to one table can no longer get files of other tables deleted. A snapshot whose parent chain loops back on itself no longer stops the expiration.
- Snapshot expiration keeps branches and tags that move during it. When a branch or tag is moved onto a snapshot that the expiration is about to remove, the expiration retries and keeps the snapshot and its files. Before, it dropped the branch or tag.
- Security: Okta and Entra ID role providers refuse subjects that consist only of dots. Such a subject would change the request URL, so that a lookup of the user's groups could return other groups. The request is refused before it is sent.
- The health check probes the server by default.
lakekeeper-plus healthcheckwithout flags now checks the server's/healthendpoint. - Database pool metrics. The server reports the
lakekeeper_catalog_pg_pool_*metrics, as Lakekeeper does. migratesets up the background tasks.lakekeeper-plus migratenow also sets up the scheduled background tasks of Lakekeeper Plus.- UI paths. The UI no longer serves a file for a path that contains
ui/a second time. Such a path now returns404. - Security updates of dependencies.
rustlsandquinn-protoare updated to fix security advisories RUSTSEC-2026-0338 to -0342 and RUSTSEC-2026-0346 to -0349.
Upgrade Notes¶
- Snapshot expiration leaves files outside the table location in place. This includes the data files of tables that still carry a
write.data.path,write.object-storage.pathorwrite.folder-storage.pathproperty. The task result counts them inskipped-outside-table-location-count. - An older binary refuses to start against a newer database.
wait-for-dband the server start now stop with an error when the database was migrated by a newer Lakekeeper Plus.wait-for-dbreads the migration state from the primary database, not from a read replica. migratewrites structured logs. Its output moves from plain text on stdout to the server's log format.
Upstream Lakekeeper changes (bump to v0.13.7)¶
All changes are in the Lakekeeper release notes of v0.13.6 and v0.13.7. The most important ones for Lakekeeper Plus:
- Security: S3 remote signing and metadata cleanup stay inside the table. The signer refuses unknown query parameters and headers, and writes that use an encryption key other than the warehouse's. A commit deletes expired metadata files only inside the table location (lakekeeper#2102).
- Remote signing with Iceberg 1.12 or later. Batch deletes, repeated deletes and repeated ranged reads no longer fail with
403 SignatureDoesNotMatch(lakekeeper#2124, lakekeeper#2104). - Tables can no longer set
write.object-storage.pathorwrite.folder-storage.path. These old names ofwrite.data.pathmake engines write data files outside the table location. Tables that already have them can remove them (lakekeeper#2044). - OPA bridge: deploy the updated policies from
authz/opa-bridge/policiesto get the fix for warehouse IDs that could not be found (lakekeeper#2052). - Shared HTTP caches can no longer give one user's response, which may contain vended credentials, to another user (lakekeeper#1947).
- Connections to ADLS, S3 and GCS time out after 10 seconds, and ADLS reuses connections (lakekeeper#2022).
v0.13.6 (2026-09-18)¶
Based on Lakekeeper OSS v0.13.5.
Bug Fixes¶
- Okta role provider: people who sign in with an email address now resolve to their groups. The user identifier was escaped for a query string rather than for a URL path, so the
@in a login likealice@example.comreached Okta as%40and every such lookup came back as a bare400. Deployments whose OIDC subject is a raw Okta user id were unaffected, which is why service principals kept working while people did not. - Okta role provider: a retried token request no longer replays its client assertion. Okta accepts each assertion once, so a DPoP nonce challenge or a throttled token request could fail with
invalid_client. Every attempt is now signed afresh. - Security: TLS handshake handling (RUSTSEC-2026-0285).
rustlsis updated to 0.23.45, which rejects handshake messages spanning a key change instead of accepting them. The handshake transcript stayed authenticated, so this could not be used to alter or complete a handshake.
Upgrade Notes¶
- OpenFGA deployments that have renamed a table, view or generic table across namespaces should run
lakekeeper openfga reconcile --mode add-and-delete-driftonce after upgrading. The upstream fix below stops the leak but cannot remove a permission edge already recorded, and the defaultadd-missingmode does not repair it.
Upstream Lakekeeper changes (bump to v0.13.5)¶
- GovCloud, China and ISO region support. Vended-credential policies now carry the correct ARN partition, derived automatically from the region, endpoint or role ARN, so
AssumeRolesucceeds for buckets outside the commercial partition (lakekeeper#1928). - S3 request signing for generic tables (lakekeeper#1910).
- Fixed a permissions leak: a table, view or generic table renamed into another namespace kept inheriting grants from the namespace it left (lakekeeper#2013).
- Renaming a table onto a name that is already taken now returns
409 Conflictinstead of404 Not Found, matching the Iceberg REST spec, and renaming onto a soft-deleted name succeeds (lakekeeper#1955).
v0.13.5 (2026-08-26)¶
Based on Lakekeeper OSS v0.13.3.
Highlights¶
- Improved memory behaviour on long-running instances. Conditions that could, under some circumstances, prevent freed memory from being returned to the OS are addressed.
Features¶
- New memory metrics.
lakekeeper_jemalloc_*separates live heap from memory the allocator is holding back;lakekeeper_http_connectionsreports open connections. - The table maintenance cache reports what it holds:
lakekeeper_cache_weighted_bytes{cache_type="table_metadata"}andlakekeeper_cache_instances, with hits and misses in the sharedlakekeeper_cache_*series.
Bug Fixes¶
- Transparent huge pages could prevent freed memory from being returned to the OS. On nodes with
THP=always, the default on common EKS AMIs, resident memory could grow for the life of the process. - The manifest cache under-counted its entries, so under some circumstances its 128 MiB budget did not bind during table maintenance.
- The UI asset cache keyed on an unvalidated header, so variants of
x-forwarded-prefixcould each add an entry to a cache with no expiry. - Allocator metrics now report on every serving path, including
LAKEKEEPER__DEBUG__AUTO_SERVE. Memory behaviour itself was unaffected.
Upgrade Notes¶
- Idle HTTP connections now close after 75 seconds and carry TCP keepalive probes. Standard Iceberg and S3 clients retry; previously a connection whose peer had vanished could be held for the life of the process.
- Request headers above 64 KiB are rejected with 431. Request bodies are unaffected.
- Shutdown drains for at most 10 seconds before abandoning connections still open.
- Unmatched request paths report
endpoint="unmatched"in metrics instead of each creating a permanent series. Dashboards that group by raw path lose those values.
v0.13.4 (2026-08-14)¶
Based on Lakekeeper OSS v0.13.3.
Bug Fixes¶
- Audit log fields are emitted as structured JSON.
actor,action/actions,entity/entities,authorizationsandcontextwere emitted as strings containing escaped pseudo-JSON, so audit pipelines could not read them as objects without decoding each field first. They are now nested JSON objects, as documented. See Upgrade Notes. - Reduced memory growth from allocator fragmentation. The server now uses jemalloc as its global allocator. Deployments that saw
container_memory_working_set_bytesclimb steadily without returning to baseline — a glibc malloc fragmentation pattern — should see flatter memory use. The effect depends on workload, and this changes the allocator only. - JSON logs no longer carry duplicate span data. Every line included both a
spanobject and aspansarray with the same content; onlyspansis emitted now. Applies tolakekeeper-plusandlakekeeper-maintenance. LAKEKEEPER__DEBUG__LOG_AUTHORIZATION_HEADERnow applies to UI-server routes. The setting was silently ignored there, so enabling it produced noauthorizationfield on those request spans.
Upgrade Notes¶
- Audit log consumers must read objects, not strings. If your pipeline JSON-decodes the audit fields a second time to get at their contents, that step now fails or double-decodes — read them directly instead. The previous string form parsed only by luck: Rust
Debugescapes non-ASCII as\u{1F600}, which is not valid JSON, so any field carrying such text would have broken the parse outright. Consumers that already tolerate both shapes need no change, and rollout order does not matter for them.
v0.13.3 (2026-07-24)¶
Based on Lakekeeper OSS v0.13.3.
Highlights¶
- Admission-gate roles now take effect. Roles granted by a
role_grantingadmission check are finally evaluated by authorization — completing the external admission gate shipped in v0.13.0, whose granted roles previously never reached Cedar.
Features¶
- Apply admission-gate roles in Cedar authorization. A new
AdmissionRoleProvider(an uncached role-provider-chain leaf, mirroring the token role provider) serves the caller's admission-granted roles under their configured provider id; Cedar materialises them asRoleentities and evaluates policies against them. Plus wires one provider per role-provider id the gate can mint under, so a gate-only deployment still resolves roles. - No-Access page for instance-level 403. An authenticated caller denied access to the instance (e.g. rejected by the admission gate) now lands on a dedicated No-Access page with proper 403 routing, instead of a broken view. (console v0.16.4)
Upgrade Notes¶
- Conflicting role-provider ids now fail fast. A gate-minted
role_provider_idthat collides with a configured or token role-provider id is rejected at startup withExtraProviderIdConflict— give the gate's minted roles a distinct provider id. - Admission roles apply under Cedar only. With the OpenFGA authorizer, or Cedar in externally-managed mode, admission-granted roles are not applied; the server logs a warning at startup so a misconfiguration is visible.
v0.13.2 (2026-07-23)¶
Based on Lakekeeper OSS v0.13.3.
Bug Fixes¶
- Maintenance page. Console bump to 0.16.3 (console-components 0.17.2, console-plus-components 0.11.0). Redesigned maintenance date-range filters, suppressed spurious 403 notifications for maintenance tasks, and fixed the Home page chart title.
v0.13.1 (2026-07-20)¶
Based on Lakekeeper OSS v0.13.3.
Highlights¶
- Okta role provider. Resolve a user's Okta group memberships to Lakekeeper roles via the Okta management API — private-key-JWT client auth with DPoP (RFC 9449) proofs enabled by default.
- Provider-synced roles are now protected. Roles owned by a configured role provider (Okta, Entra, LDAP, or token IdP) can no longer be mutated through the management API, so the next provider sync can't silently clobber manual edits.
Features¶
- Okta role provider (with DPoP). Group memberships resolved via
GET /users/{id}/groups(Link-header pagination, keyed by immutable group id). OAuth2 client-credentials + private-key-JWT (JWK or PEM key); DPoP on by default with ephemeral P-256 proofs and nonce challenge/replay handling — opt out to Bearer. Requires theokta.users.readscope; wrapped in the shared role cache. See the Okta role-provider docs. - Managed-role write protection. The Cedar authorizer now reports its configured provider namespaces to the management-API guard, so create / update / delete / source-system rebind / member (un)assignment on a provider-owned role is rejected with
400 ManagedRoleImmutable. Nativelakekeeperroles and the reservedsystemnamespace are never included, so API-native and catalog-managed roles stay writable. Active only when a role provider is configured. - Post-logout redirect controls. Two new UI env vars —
LAKEKEEPER__UI__OPENID_POST_LOGOUT_REDIRECT_URLandLAKEKEEPER__UI__OPENID_POST_LOGOUT_REDIRECT_DISABLED. - Static-asset caching in the UI server. Per-class
Cache-Controlplus weakETag/304on bundled assets: content-hashedassets/*are cached immutably and the DuckDB WASM is no longer re-downloaded on every load, whileindex.htmlstays uncached so runtime config placeholders remain fresh.
Bug Fixes¶
- Maintenance page for warehouse-only permissions. Console bump to 0.16.1 (console-components 0.17.1) fixes the maintenance view for users who hold only warehouse-level permissions.
Upgrade Notes¶
- Provider-role edits now return
400 ManagedRoleImmutable. If you previously edited provider-synced roles (Okta/Entra/LDAP/token) through the management API, those calls are now rejected — such edits were overwritten by the next sync anyway. Manage those roles at the source. No migration. - Building Plus from source: the Kubernetes client stack moved to k8s-openapi 0.28 / kube 4.0 (pulled in by the upstream limes 0.4.2 bump). Prebuilt binaries and images are unaffected.
Upstream Lakekeeper changes (up to Lakekeeper v0.13.3)¶
Notable for Plus users:
- Configurable Kubernetes subject source. LAKEKEEPER__KUBERNETES_AUTHENTICATION_SUBJECT_SOURCE=username derives a service account's Lakekeeper user id from system:serviceaccount:<namespace>:<name> (stable across clusters) instead of the per-cluster uid (default, unchanged), so Kubernetes roles and instance admins can be pre-provisioned (lakekeeper#1899).
- Reject role writes in provider-managed namespaces — the upstream API guard behind the managed-role protection above (lakekeeper#1891).
- Stop evaluating a discarded Select on target-view load, avoiding a spurious authorization check (lakekeeper#1886).
v0.13.0 (2026-07-02)¶
Based on Lakekeeper OSS v0.13.1.
Highlights¶
- Microsoft Entra ID (Graph) role provider. Resolve a user's transitive Entra group memberships into Lakekeeper roles — with secret, certificate, managed-identity, and workload-identity credentials, sovereign-cloud support, and built-in throttling/retry.
- External admission gate. A new post-authentication seam can ask your control plane whether an already-authenticated caller may use this instance — for IdPs that issue broad, non-instance-scoped tokens — and contribute the caller's resolved roles.
- Console overhaul. The bundled UI jumps to v0.13.2: a Files/storage explorer with in-browser Parquet/Avro/CSV preview, per-entity action menus, datasets as a first-class entity, redesigned view and table-health pages, a Role Members tab, and an enterprise usage-report builder.
Features¶
- Entra ID / Microsoft Graph role provider. Paged
transitiveMemberOfresolution; credential methods secret / certificate / managed-identity / workload-identity; public, US-gov, and China clouds; retries on 429 (honoringRetry-After) and transient 5xx. - AD range retrieval for LDAP attribute-mode groups. Active Directory returns >1500 group values under a ranged
memberOf;range=…key; attribute mode now walks the range windows, so users in many groups are no longer silently truncated. OpenLDAP/389-DS behavior is unchanged. - External enforce-endpoint admission gate (
lakekeeper-admission-enforce). Configurable named checks POST to your endpoint; the HTTP status is the decision (2xx allows and grants the check's role,403denies, anything else fails closed with503+Retry-After). Allow and deny are both cached; caller bearer-token relay is opt-in and never logged. - Persist OIDC token roles for DEFINER views. Opt-in via
LAKEKEEPER__ROLE_PROVIDER_CHAIN__PERSIST_TOKEN_ROLES(default off) — mirrors a user's OIDC-token roles into the catalog so authorization can evaluate them when the user isn't the live caller, e.g. a DEFINER view running as its owner. Write-gated; no migration. - Generic-table parity in Cedar authorization. Non-Iceberg generic tables (e.g. Lance, Delta) now resolve and authorize through the Cedar surface exactly like tables and views.
- Destructive-delete context for Cedar policies.
force/purge/recursiveand a warehousesoft_delete_enabledattribute are now in the Cedar request context, so a policy can forbid hard deletes that would bypass configured soft-deletion. - Role-membership actions in Cedar. The new manage/read role-assignment actions map to dedicated fine-grained Cedar actions, so policy authors control their bundling.
- Destination-aware role source-system rebind. A dedicated
update_source_systemCedar action exposes the target provider/source, so rebinds can be gated by destination — something the coarse upstream OpenFGA relation cannot express. - Per-decision policy trace in authorization audit. Audit events and the
/checkendpoint now record which Cedar policies determined each allow/deny outcome. - Schedule maintenance directly.
expire_snapshotsandremove_orphan_filescan be triggered per table via the task-queue schedule endpoint, without waiting for a commit hook.
Bug Fixes¶
- Corrupt-manifest orphan-files task no longer retries forever. A permanent failure (e.g. a corrupt Avro manifest) is now classified permanent and not requeued, instead of failing silently and re-running every day. Maintenance workers (
remove_orphan_files,expire_snapshots) also persist a readable failure reason, surfaced in the task-details API — no server-log access required.
Breaking Changes¶
- Default storage layout is now flat (inherited from upstream Lakekeeper 0.13): new namespaces use
<base>/<tabular-uuid>instead of nesting tabulars under the parent-namespace UUID. Not retroactive — existing namespaces and paths are unchanged — so explicitly configure the full-hierarchy layout if you need the old behavior for new namespaces (lakekeeper#1853).
Upgrade Notes¶
- Encrypted tables are skipped by maintenance.
expire_snapshotsandremove_orphan_filesnow detect Iceberg native encryption (format v3) via the immutableencryption.key-idproperty and skip such tables — Lakekeeper cannot read their encrypted manifests, and processing anyway risked deleting live data. Manually scheduling either task on an encrypted table returns400. - Downgrade protection (upstream):
serverefuses to start against a database already migrated by a newer binary. After a rollback, start the older binary withserve --force-start, accepting the schema-incompatibility risk (lakekeeper#1861). - Docker base images moved from Debian 12 (bookworm) to Debian 13 (trixie).
- Building Plus from source: the catalog Postgres backend and the NATS/Kafka event backends are now separate upstream crates (
lakekeeper-storage-postgres,lakekeeper-events-nats,lakekeeper-events-kafka). Prebuilt binaries and images are unaffected (lakekeeper#1812, lakekeeper#1814).
Upstream Lakekeeper changes (up to Lakekeeper v0.13.1)¶
Rolls up OSS v0.12.4, v0.13.0, and v0.13.1 (full list in the Lakekeeper release notes). Notable for Plus users:
- Generic Table API — register non-Iceberg tables (Lance, Delta) as first-class generic tables with credential vending and full authorization (lakekeeper#1673, lakekeeper#1813); surfaced in Plus through the Cedar generic-table parity above.
- Operator-owned warehouses. A managed_by marker locks warehouse spec mutations (delete, rename, (de)activate, storage profile, protection, format-version policy) to instance admins (lakekeeper#1828).
- Authorizer-independent role-membership API — one management surface to list/add/remove a role's members regardless of the configured authorizer (lakekeeper#1829).
- Multiple OIDC providers at once via LAKEKEEPER__OPENID_PROVIDERS (e.g. Okta for users + a cloud issuer for service accounts) (lakekeeper#1760).
- Microsoft OneLake / Fabric storage profile, including workspace private-link endpoints (lakekeeper#1852).
- Per-warehouse table format-version policy — allowed Iceberg format versions and an optional default per warehouse (lakekeeper#1786).
- Customer-managed KMS encryption — warehouses with aws-kms-key-arn advertise s3.sse.type=kms, so vended-credential writes use your KMS key (lakekeeper#1847).
- Cache hardening for large fleets — single-flight read-throughs and TTL jitter cut thundering-herd load on the database and on rate-limited STS/SAS endpoints (lakekeeper#1833, lakekeeper#1837).
- /health now returns 503 (not 200) when unhealthy, so Kubernetes HTTP probes detect it (lakekeeper#1802).
- Postgres migration locks are transaction-scoped, so a failed migration can't leak an advisory lock that blocks future migrations (lakekeeper#1790).
v0.12.2 (2026-05-26)¶
Highlights¶
- Orphan-file cleanup now schedules itself adaptively per table — running more often where files accumulate and backing off where they don't — with a new dry-run mode.
- The LDAP role provider can resolve groups via subtree Search and conditional Branching, not just the
memberOfattribute.
Features¶
- Adaptive orphan-file scheduling. The remove-orphan-files worker now self-tunes its cadence based on how fast reclaimable data builds up, and adds a dry-run mode that reports what it would delete. Orphan removal is now opt-in via
enable-remove-orphan-files; default retention raised from 3 to 7 days. See the Table Maintenance docs for full config. - LDAP group resolution modes. Resolve group memberships via
Search(paged subtree) orBranching(per-user-DN rules) in addition to thememberOfattribute; the resolution mode is recorded in audit logs. - Build metadata in Server Info. Server Info now reports Lakekeeper, Enterprise, and Console versions and commit SHAs, so deployed builds are easy to identify.
Breaking Changes¶
- The orphan-files task-queue API was renamed
remove_orphaned_files→remove_orphan_files(paths, config schemas, and worker/enable fields).
Upgrade Notes¶
- Update any automation/IaC to the new
remove_orphan_filestask-queue path and schema names. - Orphan removal is now opt-in (it ran by default in 0.12.1): set
enable-remove-orphan-files=trueto keep it active. Default retention is now 7 days.
Upstream Lakekeeper changes (bump to v0.12.3)¶
- Core and extension database migrations now apply atomically — no partial-migration state (lakekeeper#1768).
- Fixed table property removal being lost when no properties remained (lakekeeper#1767).
- New read-only maintenance mode for the server (lakekeeper#1765).
- Users may now share an email address — the unique-email constraint was dropped (lakekeeper#1755).
- New
LAKEKEEPER__UI__ENABLE_SURVEYSflag to opt out of in-console surveys (lakekeeper#1750).
v0.12.1 (2026-05-10)¶
Features¶
- Remove Orphan Files. New maintenance capability that reclaims storage by deleting data, manifest, and metadata files no longer referenced by any snapshot — available as a server background worker and as a
remove-orphan-filessubcommand (with dry-run). Enabled by default; setLAKEKEEPER__TASK_REMOVE_ORPHANED_FILES_WORKERS=0to disable. Respectsgc.enabledand per-table opt-out properties. See the Table Maintenance docs for full config. - Bounded orphan-files runtime. Cap how long a single orphan-files run may take with a configurable max run time.
Bug Fixes¶
- Warehouse rename no longer leaves a stale name in the UI table preview (bundled UI 0.7.12).
Upgrade Notes¶
- The orphan-files worker is enabled by default (2 workers); set
LAKEKEEPER__TASK_REMOVE_ORPHANED_FILES_WORKERS=0to disable. By default it only deletes files older than 3 days and honorsgc.enabled/ per-table opt-out.
Upstream Lakekeeper changes (bump to v0.12.2)¶
- OpenFGA: rebuild/reconcile authorization tuples from the catalog, and support switching an existing server to OpenFGA (lakekeeper#1731, lakekeeper#1733).
- OPA Trino batch authorization gains a broad-access fast path for warehouses/namespaces (lakekeeper#1727).
- Storage: dropped the opendal dependency and now validates vended credentials via
lakekeeper_io(lakekeeper#1737). - ADLS fixes: correct SAS-token key removal and
%-encoding in blob names (lakekeeper#1746).
v0.12.0 (2026-04-21)¶
Highlights¶
- Cedar authorization matured into a configurable, inspectable system: derive user attributes from identity fields, reference roles by global ID, and use a new resolve-entities API + Console tabs to see exactly what drives a decision.
- Role providers resolve user roles from external sources — including LDAP groups and table properties — with caching, metrics, and audit.
- Console: a visual Cedar Policy Builder (beta) with a Cedar-aware editor, authorization-inspection tabs, and new statistics dashboards.
- Container images now default to
ubi10(breaking — see below).
Features¶
- Cedar user identity derivations. Extract attributes from identity fields with named-capture regex rules (optional
lowercase/uppercasetransform) and match policies on the derived values. - Global role IDs in policies. Reference provider-scoped global role IDs as Cedar property values, and use short-form roles without a default provider.
- Resolve-entities API.
POST /management/v1/permissions/cedar/resolve-entitiesreturns the Cedar entities for any resource — for debugging why a decision was reached. - SelectView action. Adds
select/SelectView(andgrant_select) for views, aligning with the upstream data-plane authorization split. - Role-provider subsystem. LDAP Group Provider + token-provider chain, roles parsed from table properties, caching with stale-fallback and metrics, and an opt-in audit event for resolved roles — wired into the Cedar authorizer. Configure via
ROLE_PROVIDER_FILE(TOML), overridable per-field by env vars. - Richer permission-introspection audit.
introspect_permissionslogs now include the inner check tuples and their individual decisions. - Console: Cedar Policy Builder (beta). Visual editor/builder with a CodeMirror Cedar editor (highlighting, autocomplete, inline diagnostics, format/validate via cedar-wasm) and live Evaluate.
- Console: authorization inspection + dashboards. Tabs for entity/policy sources, schema, and resolve-entities; new Home and Warehouse statistics dashboards; storage-layout configuration.
Bug Fixes¶
- Cedar: correctness fixes around short-form role tags, per-request provider-ID derivation, Role subjects, and resolve-entities server gating.
- Maintenance: expire-snapshots now removes statistics / partition-statistics from metadata, avoiding dangling references to deleted files.
- TLS: added webpki and native root certs to the S3 client and UBI images, fixing handshake failures in some environments.
- Console: correct handling of sub-namespaces containing dots; per-tab 403 keeps the navigation rail visible.
Breaking Changes¶
- Container images now default to
ubi10; theubi9-based image remains available under a separate tag.
Upgrade Notes¶
- If you pin the
ubi9base image (e.g. FIPS/compliance), switch to the dedicatedubi9tag — the default is nowubi10. - Role-provider config can be supplied via
ROLE_PROVIDER_FILE(TOML), with env vars overriding per field — review precedence if you set both.
Upstream Lakekeeper changes¶
- Instance Admins — server-wide admin role independent of project membership (lakekeeper#1716).
- Idempotency keys for safely retrying mutating requests (lakekeeper#1671).
referenced-byto discover views referencing a table/view (lakekeeper#1627).- Configurable trusted engines in request metadata for authorization (lakekeeper#1629).
- Protect immutable table properties (e.g.
encryption.key-id) during commits (lakekeeper#1700). - Faster list namespaces/tables/views (lakekeeper#1618).