Skip to content

v8.2.0

Latest

Choose a tag to compare

@github-actions github-actions released this 10 Aug 18:18
· 82 commits to master since this release
v8.2.0
42f7fdc

Table of Contents

Changes in 8.2.0

Summary

  • Security - Do not leak internal error details in webdav error responses: #12398
  • Security - Make OIDC group sync opt-in: #12490
  • Security - Block password and account changes via PATCH /graph/v1.0/me: #12493
  • Bugfix - Always set an audit action for share updates: #7661
  • Bugfix - Fix the proxy readiness check for NATS: #10661
  • Bugfix - Honor $select=actions on the drive item permissions endpoint: #10816
  • Bugfix - Keep group memberships when the OIDC groups claim is absent: #11435
  • Bugfix - Pass the space ID when purging revision blobs: #11644
  • Bugfix - Return 404 when deleting a non-existing link share on a space: #12266
  • Bugfix - Fix PostgreSQL container restart loop in Keycloak deployments: #12359
  • Bugfix - Prevent panic in presigned URL auth when signing key is missing: #12384
  • Bugfix - Fix double HTML-escaping of notification emails for multiple recipients: #12413
  • Bugfix - Re-verify access tokens with an expired userinfo cache entry: #12414
  • Bugfix - Keep shares visible in sharedWithMe when a resource cannot be statted: #12430
  • Bugfix - Ensure the redirect URI for the IDP is valid: #12444
  • Bugfix - The auth-app will create the user's home if needed: #12457
  • Bugfix - Fix the empty mount ID for reva config: #12492
  • Bugfix - Rate-limit the exportPersonalData endpoint: #12516
  • Bugfix - Apply the role allowlist on permission updates: #12540
  • Bugfix - Restore hover feedback in high-contrast and dark themes: #12613
  • Bugfix - Preserve accessibility focus in the file versions sidebar: #12630
  • Bugfix - Fix low-contrast form controls in dark and vault themes: #12639
  • Bugfix - Stop breadcrumb items from being announced twice: #12643
  • Bugfix - Remove unneeded keyboard focus stops: #12645
  • Bugfix - Fix keyboard navigation in "New" and "Upload" dropdown menus: #12646
  • Bugfix - Announce IDP sign-in errors and fix keyboard use: #12649
  • Bugfix - Show vault-shared mountpoints in the vault drive list: #12656
  • Bugfix - Prevent deleting your own account in the user management: #12661
  • Bugfix - Log unmapped thumbnail errors and always report a sabredav exception: #12667
  • Bugfix - Fix concurrent map access when listing shares: #12673
  • Bugfix - Keep bind config in sync when resetting a service user password: #12716
  • Bugfix - Allow renaming, moving and editing files with the editor-lite role: #12721
  • Bugfix - Fix invisible group icon in share collaborator list: #12722
  • Bugfix - Return correct issuerAssignedId on /me: #12727
  • Bugfix - Vault navigation labels not updating on switch: #12729
  • Bugfix - Do not collide vault and non-vault share mountpoints: #12730
  • Bugfix - Remove keyboard focus from open file name in top bar: #12752
  • Enhancement - Replace embedded IDP React SPA with server-rendered login page: #12086
  • Enhancement - Add ocis shares clean-corrupt-public-shares maintenance command: #12494
  • Enhancement - Harden OCM create share: #12496
  • Enhancement - Clean up the deployment examples: #12521
  • Enhancement - Allow disabling the last sign-in timestamp update: #12522
  • Enhancement - Add configurable software license and help page links: #12528
  • Enhancement - Configurable logo click-through URL: #12529
  • Enhancement - Add option to disable public link sharing: #12542
  • Enhancement - Add option to disable direct (user/group) sharing: #12542
  • Enhancement - Add audience restriction for OIDC access tokens: #12581
  • Enhancement - Eliminate redundant LDAP read-after-write on create and update: #12618
  • Enhancement - Improve page structure on several pages: #12637
  • Enhancement - Show the select-all checkbox label in tile view: #12640
  • Enhancement - Retry LDAP operations against a lagging replica: #12672
  • Enhancement - Add an opt-in bounded LDAP connection pool: #12688
  • Enhancement - Bump dependencies: #12766

Details

  • Security - Do not leak internal error details in webdav error responses: #12398

    The webdav service returned raw internal error messages to the client when a
    server-side error occurred. For example, a thumbnail request with a null byte in
    the filename and ?preview=1 could trigger a 500 Internal Server Error whose
    body exposed the internal storage filesystem path (information disclosure).

    Server-side error handlers now return a generic, user-relevant message to the
    client, while the detailed error is only logged server-side.

    #12398

  • Security - Make OIDC group sync opt-in: #12490

    What changed. PROXY_AUTOPROVISION_CLAIM_GROUPS now defaults to "", which disables OIDC group membership sync (and, with it, creation of local groups from claim values). It previously defaulted to groups. Setting it to a non-empty claim name restores the previous behaviour unchanged: memberships are synced and groups named in the claim are created if they do not exist locally.

    Why. With PROXY_AUTOPROVISION_ACCOUNTS=true and the previous groups default, the proxy synced group memberships from the OIDC groups claim on every authenticated request out of the box, creating local groups for any claim value that did not already exist. In identity providers that let ordinary users create groups with arbitrary names, this allowed an unprivileged user to inject group names into oCIS. Defaulting the claim to empty makes group sync an explicit opt-in.

    Upgrade note. Deployments that set PROXY_AUTOPROVISION_CLAIM_GROUPS explicitly are unaffected. Deployments that relied on the previous groups default without setting it will stop syncing group memberships after upgrade; set PROXY_AUTOPROVISION_CLAIM_GROUPS=groups to restore the previous behaviour.

    Note: matching claim values to existing local groups is still done by display
    name. Hardening that matching is tracked separately and is not part of this
    change.

    #12490

  • Security - Block password and account changes via PATCH /graph/v1.0/me: #12493

    PATCH /graph/v1.0/me no longer accepts passwordProfile, accountEnabled, or
    onPremisesSamAccountName. Use POST /graph/v1.0/me/changePassword to change
    your password.

    #12493

  • Bugfix - Always set an audit action for share updates: #7661

    Share-update audit events were written with an empty action and a message of
    updated field '', because the conversion read the deprecated
    ShareUpdated.Updated field, which reva no longer populates (it now sets
    UpdateMask). Received-share declines were also not audited correctly because
    the conversion matched SHARE_STATE_DECLINED, which is not a CS3 share state
    (the enum value is SHARE_STATE_REJECTED), again producing an empty action and
    message.

    The conversion now derives the updated field and action from UpdateMask
    (falling back to the deprecated field), maps SHARE_STATE_REJECTED to the
    declined action, and uses a generic, non-empty action for any unrecognized
    update field or share state, so every audit entry carries a meaningful,
    countable action.

    #7661
    #12423

  • Bugfix - Fix the proxy readiness check for NATS: #10661

    The proxy readiness check passed the events cluster ID instead of the events
    endpoint to the NATS reachability check. NATS then tried to resolve the cluster
    ID (e.g. ocis-cluster) as a host name, which always failed, so the proxy
    /readyz endpoint reported the service as not ready even when NATS was
    reachable. The check now uses the events endpoint, consistent with every other
    service.

    #10661
    #12421

  • Bugfix - Honor $select=actions on the drive item permissions endpoint: #10816

    Listing the permissions of a drive item with
    $select=@libre.graph.permissions.actions.allowedValues still returned the
    roles allowedValues as well. The handler only had a projection for the roles
    selection (@libre.graph.permissions.roles.allowedValues), which drops the
    actions, but no symmetric handling for an actions-only selection, so the roles
    were always included. The actions selection now drops the roles allowedValues
    (and, like the roles selection, skips the share lookup since only the allowed
    values are requested).

    #10816
    #12419

  • Bugfix - Keep group memberships when the OIDC groups claim is absent: #11435

    When auto-provisioning group memberships from an OIDC claim, the proxy
    reconciled the user's groups against the groups claim and removed them from any
    group not present in the claim. If a token carried no groups claim at all —
    for example a token issued for an OIDC client that has no groups mapper
    configured, such as a dedicated desktop-client registration — the parsed group
    set was empty and the user was removed from all of their groups.

    The sync is now skipped when the groups claim is absent or null in the token. A
    present-but-empty claim is still treated as a legitimate "no groups" and
    reconciled as before. This mirrors the guard the role-assignment path already
    has for a missing roles claim.

    #11435
    #12420

  • Bugfix - Pass the space ID when purging revision blobs: #11644

    The revisions purge command removed a revision's metadata but did not delete
    its blob, because it called the blobstore without the space ID. The blobstore
    builds the blob path from the space ID and blob ID, so an empty space ID
    targeted the wrong path: the deletion was a no-op (S3) or missed the file
    (POSIX), leaving the blob orphaned while the revision was already removed. The
    space ID parsed from the revision path is now passed to the blobstore.

    #11644
    #12422

  • Bugfix - Return 404 when deleting a non-existing link share on a space: #12266

    Deleting an already-removed link share via DELETE /graph/v1beta1/drives/{driveID}/root/permissions/{permissionID} returned 400 Bad Request instead of 404 Not Found. The underlying reva RemovePublicShare
    and RemoveShare handlers now propagate not-found errors as CODE_NOT_FOUND
    rather than CODE_INTERNAL, ensuring the correct 404 HTTP response is
    returned.

    #12266

  • Bugfix - Fix PostgreSQL container restart loop in Keycloak deployments: #12359

    The PostgreSQL volume was mounted directly at /var/lib/postgresql/data. On
    ext4 storage backends, Docker creates a lost+found directory at the volume
    root, causing PostgreSQL's initdb to fail because the data directory is not
    empty. This resulted in the container entering a restart loop.

    The volume mount path has been changed to /var/lib/postgresql so that
    PostgreSQL creates the data/ subdirectory itself, avoiding the conflict.

    #12359

  • Bugfix - Prevent panic in presigned URL auth when signing key is missing: #12384

    The presigned-URL authenticator read the per-user signing key from a store and
    indexed the first record without checking that the result was non-empty. When
    the store returns an empty result without an error — which the noop store
    does, and OCIS_CACHE_STORE=noop also switches the presigned-URL signing-key
    store to noop — every signed-URL request panicked with index out of range [0] with length 0 (recovered per request as an HTTP 502), so all signed-URL
    downloads failed. The authenticator now guards the lookup and returns a normal
    authentication error instead of panicking; it also no longer returns a nil error
    when the stored key is empty.

    #12384
    #12418

  • Bugfix - Fix double HTML-escaping of notification emails for multiple recipients: #12413

    The notifications service reuses the same template variables map for every
    recipient of an event (for example when a group is invited to a space). The
    helper that HTML-escapes those variables for the HTML email body escaped the map
    in place, so every recipient after the first received a plain-text body
    containing HTML entities and an HTML body with one additional layer of escaping
    per recipient (a space named R&D became R&D). The helper now returns
    a new map and leaves the shared variables untouched, so every recipient renders
    from the original values.

    #12413

  • Bugfix - Re-verify access tokens with an expired userinfo cache entry: #12414

    The proxy authenticated requests against a cached userinfo entry. When the
    cached entry's expiry had passed, the request was rejected outright instead of
    re-verifying the access token. The cached expiry is not always the real token
    expiry — for opaque access tokens it falls back to the configured cache TTL
    — so a still-valid token could be rejected just because its cache entry aged
    out, causing spurious logouts (most noticeable under frequent PROPFIND
    requests). The proxy now treats an expired cache entry as a cache miss and
    re-verifies the access token, while a genuinely expired or invalid token is
    still rejected by the re-verification.

    #12414

  • Bugfix - Keep shares visible in sharedWithMe when a resource cannot be statted: #12430

    The graph sharedWithMe handler resolves each received share by fanning out a
    per-resource Stat call with a concurrency limit, all sharing the request
    context. When a Stat failed for any reason (slow or stuck downstream, deleted
    space, gateway error, deadline exceeded) the worker logged at debug and returned
    without emitting a drive item, so the share was silently omitted from the
    response and the handler still returned 200 OK with a partial,
    non-deterministic list. A single chronically-slow share could therefore make
    other, recently-accepted shares intermittently invisible, and repeated calls
    returned different subsets of the user's shares.

    The handler now:

    • bounds each per-share Stat with its own timeout derived from the request
      context, so one slow resource can no longer consume the deadline shared by all
      the other shares. The bound is configurable via
      GRAPH_RECEIVED_SHARES_STAT_TIMEOUT (default 10s); - returns a degraded drive
      item built from the data already present in the share record (ids, permissions,
      grantees, timestamps, mountpoint name) when the resource cannot be statted due
      to a transient or indeterminate failure (timeout, slow or unavailable
      downstream), so the share stays visible instead of intermittently disappearing.
      A genuinely missing resource or revoked access (for example after the sharer was
      deleted) still drops the share, as before; - logs the dropped/degraded shares at
      warning level with a per-request count for operator visibility.

    #12430

  • Bugfix - Ensure the redirect URI for the IDP is valid: #12444

    The URI sent as redirect URI for the IDP will be validated in oCIS. Invalid URIs
    will return a 500 error. Note that this should never happen under normal
    circumstances.

    #12444
    #12479

  • Bugfix - The auth-app will create the user's home if needed: #12457

    When the user logs in, his home must be created. This happens automatically
    during login via OIDC (web access). Some recent changes in the code broke this
    behavior when the user logs in via auth-app. Now, this behavior is restored, and
    the user's home will be created when the user logs in via auth-app.

    #12457

  • Bugfix - Fix the empty mount ID for reva config: #12492

    We fixed the empty mount ID for storage-users

    #12492

  • Bugfix - Rate-limit the exportPersonalData endpoint: #12516

    We've added a rate limit to the exportPersonalData endpoint to mitigate an
    authenticated application-level denial-of-service. Rate-limit per endpoint path
    carries the userID, so effectively per user. The endpoint is now limited to 5
    requests per minute.

    #12516

  • Bugfix - Apply the role allowlist on permission updates: #12540

    The PATCH permission and space-root permission handlers now consult the
    administrator role allowlist when validating a request, consistent with the
    invite handler.

    #12540

  • Bugfix - Restore hover feedback in high-contrast and dark themes: #12613

    The Light and Dark High-Contrast themes set the background-highlight color token
    equal to the default page background, making hover backgrounds indistinguishable
    from the resting background wherever background-highlight was used for
    interactive feedback, such as the global search results dropdown. The
    non-high-contrast Dark theme had the same collision.

    Background-highlight now matches background-hover in the affected theme
    definitions, and the search results dropdown and create-shortcut context menu
    now use the background-hover color directly for their hover and active states,
    since background-highlight is otherwise used for static surfaces like cards,
    modals and form fields rather than interaction feedback.

    #12613

  • Bugfix - Preserve accessibility focus in the file versions sidebar: #12630

    Opening the file versions panel with a keyboard or screen reader could move
    focus to the main page, and restoring a version could briefly move focus to the
    main page before selecting the sidebar's back button. The sidebar now manages
    focus throughout panel transitions and loading states, restores focus to the
    control that opened it when closed, and returns focus to the restored version's
    Restore button after the operation completes. Version dates and action labels
    also provide clearer context for screen reader users without duplicate
    announcements or additional tab stops.

    #12630

  • Bugfix - Fix low-contrast form controls in dark and vault themes: #12639

    Several form controls were hard to see against dark and vault theme backgrounds.
    The view-options range slider had no visible track border and relied on an
    opacity dip on hover, making it barely visible at rest. The switch component's
    off-state track and thumb, and its on-state thumb, used colors too close to
    their surrounding background to read as a toggle. The select combobox's
    highlighted/selected option text used a color too close to the highlight
    background.

    The global search input's text color was forced with !important, overriding
    the theme-specific search text color some themes set, which made typed text
    render in white on a white search input background in the vault "Dark Theme –
    High Contrast". The search placeholder color also used an invalid CSS custom
    property fallback (a bare property name instead of a nested var()), silently
    breaking the placeholder color for any theme that didn't define a
    search-specific placeholder token, and the vault "Dark Theme"'s placeholder
    color was too close to its input's text and border color to read as muted.

    The slider now has a visible border and no longer dims on rest, the switch and
    select now use colors with sufficient contrast against their backgrounds, the
    !important override blocking theme-specific search colors has been removed,
    the invalid placeholder fallback has been fixed, and the vault "Dark Theme"
    placeholder color has been changed to one with visible contrast against the
    input text.

    #12639

  • Bugfix - Stop breadcrumb items from being announced twice: #12643

    Each breadcrumb list item had tabindex="0", putting the item itself in the
    keyboard/screen reader focus order in addition to the link or button nested
    inside it. This caused every breadcrumb segment to be announced twice in a row.
    The list item is no longer a separate focus stop; only its inner link or button
    is, while the item remains focusable enough for existing drag-and-drop styling
    to keep working.

    #12643

  • Bugfix - Remove unneeded keyboard focus stops: #12645

    Some icons and date columns in tables (spaces list, file list) could
    unexpectedly receive keyboard focus even though they don't trigger any action,
    adding unnecessary stops when tabbing through the page. The contextual helper
    icon also carried a label that duplicated the label already present on its
    surrounding button. These redundant focus stops and duplicate labels have been
    removed.

    #12645

  • Bugfix - Fix keyboard navigation in "New" and "Upload" dropdown menus: #12646

    Opening the "New" or "Upload" dropdown menu in the Files app toolbar did not
    move focus into the menu, so pressing the arrow keys had no effect on the
    highlighted item, unlike the existing right-click context menu. Both dropdowns
    now focus their first item on open, restoring arrow key navigation.

    #12646

  • Bugfix - Announce IDP sign-in errors and fix keyboard use: #12649

    The login, consent, and account chooser pages did not announce error messages
    when they appeared, and invalid username/password fields gave no indication of
    their error state. The consent screen's scope list also had no programmatic link
    between each entry and its checkbox, and the account chooser's "continue as" and
    "use another account" entries could not be reached or activated with a keyboard.
    A visible focus outline on the login form's input fields had also been removed
    with no replacement. All of these have been fixed.

    #12649

  • Bugfix - Show vault-shared mountpoints in the vault drive list: #12656

    Shares of vault resources are mountpoints hosted on the shares storage provider
    that grant into the vault storage provider. When listing spaces with the vault
    storage_id, the storage registry skipped the shares provider entirely, so the
    vault share mountpoint was missing from the vault drive list while still showing
    up in the regular drive list.

    The registry now also queries the shares provider when the vault storage id is
    requested and segregates share mountpoints by their grantStorageID, so a vault
    share only appears in the vault drive list and a regular share only in the
    regular one.

    #12656
    owncloud/reva#670

  • Bugfix - Prevent deleting your own account in the user management: #12661

    In the admin settings user management, the account you are currently logged in
    as could be selected and included in a delete action, even though the backend
    always rejects self-deletion. Deleting a selection that included your own
    account produced a "Failed to delete 1 user" error and made your own row
    temporarily disappear from the list until the page was refreshed.

    The delete action now excludes the current user from the request, so all other
    selected users are deleted while your own account is left untouched. When your
    own account is part of the selection, the delete confirmation dialog shows a
    hint that it will not be deleted.

    #12582
    #12661

  • Bugfix - Log unmapped thumbnail errors and always report a sabredav exception: #12667

    The webdav service logged failures of the thumbnails service at debug level
    only. Errors which are not a property of the requested file, such as the
    thumbnails service being unreachable, were therefore invisible at production log
    levels: a complete preview outage produced HTTP 500 responses without a single
    log line explaining them. Unmapped errors are now logged at error level, while
    expected per-file outcomes such as an unsupported file type or a file still
    being processed stay at debug level. Two of the four thumbnail handlers also
    logged without the request context, so their messages carried no request id.

    In addition, codesEnum only mapped four status codes, so error responses for
    all other codes were rendered with an empty <s:exception></s:exception>
    element. The missing entries for 403, 425 and 429 have been added and any
    remaining unmapped code now falls back to a generic exception name, so clients
    always receive a usable exception.

    #12667

  • Bugfix - Fix concurrent map access when listing shares: #12673

    Listing shares could abort the whole oCIS process with the Go runtime error
    "fatal error: concurrent map read and map write". This is an unrecoverable
    runtime fault, so it could not be caught and recovered from, and it dropped all
    connections that were in flight at that moment.

    When converting CS3 shares into Graph DriveItems, the worker goroutines read
    from the shared driveItems map while the collecting loop was already writing
    results into the very same map. The results channel is buffered, so the workers
    never blocked when handing over an item and the collecting loop started writing
    while workers were still running. The results are now collected after all
    workers have finished, which removes the overlapping access.

    Note that lowering the maximum concurrency did not avoid this, as a single
    worker could still run concurrently with the collecting loop.

    #12673

  • Bugfix - Keep bind config in sync when resetting a service user password: #12716

    Resetting an IDM service user password with ocis idm resetpassword --user-type service only changed the entry in the IDM directory. Services such as
    auth-basic, users and groups still bound to LDAP as the reva service user
    using the old bind_password from their configuration, so after a restart those
    binds failed and regular admin login started returning 401 Unauthorized.

    The command now rewrites the matching bind_password and
    service_user_passwords keys in ocis.yaml when it is present, and always
    prints the environment variables that must carry the new password for env-var
    and distributed deployments it cannot rewrite.

    #12569
    #12716

  • Bugfix - Allow renaming, moving and editing files with the editor-lite role: #12721

    We've fixed the editor-lite role ("Can edit" in the web UI). Sharees can now
    rename a file inside a shared folder, move it and change its contents. Before,
    they could only upload new files, and the web UI offered neither the rename nor
    the overwrite action.

    The role has always granted Move, but the persisted ACE format had no flag of
    its own for it: Move shared the "w" flag with InitiateFileUpload and was only
    recovered on read by assuming a grant may move whenever it may write, download
    and delete. The editor-lite role has no delete, so its Move was dropped as soon
    as the grant was written to disk, Decomposedfs.Move then refused the rename
    and propfind reported the grant as a create-only uploader. Move is now persisted
    under its own "m" flag in pkg/storage/utils/ace/ace.go; grants written before
    that flag existed carry no "m" and keep using the old inference. On top of that,
    RoleFromResourcePermissions in pkg/conversions/role.go did not treat Move as
    write, so the WebDAV permissions string lacked "NV" (rename) and "W" (overwrite)
    even for a grant that had kept its Move. Move now implies write for grants that
    do not carry delete, which leaves the OCS permissions of the deletable roles
    unchanged.

    Note: the effective permission set of the editor-lite role changed. The CS3
    resource permissions returned by NewEditorLiteRole are unchanged - Stat,
    GetPath, ListContainer, InitiateFileDownload, InitiateFileUpload,
    CreateContainer and Move, still no Delete and no ListFileVersions - but a grant
    created from it is now stored as "txrwma" instead of "txrwa", reports the OCS
    permissions 6 (create + write) instead of 4 (create), and reports the WebDAV
    permissions "SNVW" on a shared file and "SNVCK" on a shared folder instead of
    "S" and "SCK".

    The same "m" flag also restores Move for any other non-deletable grant that
    carries it. In particular the Uploader share role is affected: like editor-lite
    it is a create grant without delete, so its Move used to be dropped on
    write-back and is now preserved. This is why the previously expected-to-fail
    "sharee moves a file within a shared folder" scenarios for the Uploader role now
    pass, and the matching entries were removed from
    tests/acceptance/expected-failures-API-on-OCIS-storage.md.

    This fix DOES NOT include a migration of stored grants. Shares created with that
    role before this update keep their old grant on disk, which carries no "m" flag.
    For them, Move stays unset and the WebDAV permissions string stays unchanged,
    while the share record itself has always kept Move and therefore already reports
    the new OCS permissions. Only shares created with that role AFTER THE UPDATE get
    the new permission set. Re-creating an affected share, or updating its role,
    re-writes the grant and picks up the fix.

    #11977
    #12721
    owncloud/reva#689

  • Bugfix - Fix invisible group icon in share collaborator list: #12722

    The icon shown next to group entries in the share collaborator autocomplete list
    used a color variable that no longer resolved to a valid value, making the icon
    effectively invisible against the background. The icon now uses the correct
    default text color variable so it renders properly again.

    #12722

  • Bugfix - Return correct issuerAssignedId on /me: #12727

    The /graph/v1.0/me endpoint reported the internal user UUID as
    identities[].issuerAssignedId instead of the issuer-assigned identity (the
    OIDC sub). The endpoint took a fast path that built the user model from the
    CS3 user in the request context, which does not carry the external identity, so
    it fell back to the internal UUID. /me now always resolves the user through
    the identity backend, which reads the stored external identity and returns the
    correct value. Group memberships are still only expanded when $expand=memberOf
    is requested.

    #12727
    #12431
    #12411

  • Bugfix - Vault navigation labels not updating on switch: #12729

    The Files app navigation labels for the personal space and spaces list sometimes
    kept showing the regular names instead of the vault-specific ones after
    switching into the vault, and vice versa. This happened because the vault
    detection only looked at the plain URL path and missed cases such as hash-based
    routes or the redirect right after logging in.

    The vault detection has been centralized and now also recognizes hash-based
    vault routes and the post-login redirect target, so the navigation labels
    correctly reflect whether the user is in the vault.

    #12729

  • Bugfix - Do not collide vault and non-vault share mountpoints: #12730

    Received shares mounted from the Vault storage and received shares mounted from
    regular drives were treated as one flat namespace when computing a unique
    mountpoint name. Sharing a resource with the same name once from a regular drive
    and once from the Vault caused the second one to get a spurious (1) suffix,
    even though the two shares are rendered in completely separate, segregated lists
    and never actually collide. Mountpoint name collisions are now only checked
    against other shares within the same vault/non-vault group.

    #12730

  • Bugfix - Remove keyboard focus from open file name in top bar: #12752

    When opening a file such as a text or markdown document, the file name shown in
    the top bar could be reached via keyboard tabbing even though it was not
    clickable and triggered no action. This made keyboard navigation confusing.

    The file name is no longer part of the tab order, since it is a purely
    informational, non-interactive element.

    #12752

  • Enhancement - Replace embedded IDP React SPA with server-rendered login page: #12086

    Replaced the embedded IDP login's React SPA (pnpm, 21k LOC) with server-rendered
    HTML keeping theming and localiation support. The login page now works with
    minimal JavaScript, loads faster, and has a much smaller dependecy vulnerability
    surface.

    #12086

  • Enhancement - Add ocis shares clean-corrupt-public-shares maintenance command: #12494

    A single public-share entry with a nil/empty resource_id makes the json
    public-share manager's ListPublicShares panic with a nil-pointer dereference.
    Because the manager reads all entries and filters them in memory, that one bad
    entry poisons the endpoint for the whole tenant: every Members/permissions panel
    load and every password-protected link creation fails.

    The new ocis shares clean-corrupt-public-shares command detects and removes
    such corrupt entries. It reads the raw persistence (so it never triggers the
    panic itself) and writes back through the same metadata storage path the manager
    uses, recomputing blob size, mtime and etag automatically. It defaults to
    --dry-run and supports the jsoncs3 and json public-share drivers.

    #12494

  • Enhancement - Harden OCM create share: #12496

    CreateShare now validates the provider via GetInfoByDomain and verifies an
    accepted invite relationship via GetAcceptedUser before creating the share.

    #12496

  • Enhancement - Clean up the deployment examples: #12521

    Removed the legacy deployment example oc10_ocis_parallel and its documentation
    references. Removed coverage.out

    #12521

  • Enhancement - Allow disabling the last sign-in timestamp update: #12522

    The graph service maintains the 'oCLastSignInTimestamp' LDAP attribute of a user
    on every sign-in (when the LDAP identity backend has write access). This can
    cause a significant amount of LDAP write load, especially when the proxy's OIDC
    userinfo cache has a short TTL and sign-in events are emitted frequently.

    A new setting 'OCIS_LDAP_UPDATE_LAST_SIGNIN_DATE' /
    'GRAPH_LDAP_UPDATE_LAST_SIGNIN_DATE' (default 'true') allows disabling the
    update of the last sign-in timestamp without having to disable all LDAP writes
    ('OCIS_LDAP_SERVER_WRITE_ENABLED') or the graph events consumer. When set to
    'false' the graph service no longer listens for 'UserSignedIn' events and does
    not write the 'oCLastSignInTimestamp' attribute.

    #9942
    #12522

  • Enhancement - Add configurable software license and help page links: #12528

    Themes can now set common.urls.softwareLicense and common.urls.helpPage to
    surface deployment-specific legal/help links in the web UI. When set, links
    appear in a new "Help" menu in the topbar and on the account page.

    #12528

  • Enhancement - Configurable logo click-through URL: #12529

    We've added an optional href field to the logo theme configuration. When
    set, clicking the topbar logo navigates to the configured URL instead of the
    default files navigation. When not set, the existing default behavior is
    unchanged.

    #12529

  • Enhancement - Add option to disable public link sharing: #12542

    Added an OCIS_ENABLE_PUBLIC_SHARING config option, read by the frontend and
    sharing services. It defaults to true. When set to false, creating new
    public links is rejected and the files_sharing.public.enabled capability
    reports false so clients hide the corresponding UI. Direct sharing with users
    and groups is not affected.

    #12542

  • Enhancement - Add option to disable direct (user/group) sharing: #12542

    Added an OCIS_ENABLE_USER_SHARING config option, read by the frontend, graph,
    sharing and ocm services. It defaults to true. When set to false, creating
    new user, group or federated shares is rejected, the legacy sharees search
    endpoint returns no results, and the files_sharing.user.enabled and
    files_sharing.user_enumeration.enabled capabilities report false so clients
    hide the corresponding UI. Public link sharing and space membership are not
    affected.

    #12542

  • Enhancement - Add audience restriction for OIDC access tokens: #12581

    We added a new proxy configuration option PROXY_OIDC_ACCESS_TOKEN_VERIFY_AUD
    which lets operators restrict the JWT access tokens that are accepted to a list
    of allowed audiences. When set, a token is only accepted if one of the
    configured values is present in its aud (audience) claim or matches its azp
    (authorized party) claim. This is useful when the OIDC provider (IDP) is shared
    between multiple applications, so that tokens issued for another application are
    not accepted by ownCloud Infinite Scale.

    The check is disabled by default (empty list) to preserve the existing behavior.

    #12581

  • Enhancement - Eliminate redundant LDAP read-after-write on create and update: #12618

    The graph LDAP backend no longer re-reads an entry immediately after writing it
    just to recover the entry ID for the response. When oCIS generates the ID itself
    (GRAPH_LDAP_SERVER_UUID disabled), the create response is now synthesized from
    the data already sent to the directory, and update responses are built by
    folding the applied modifications onto the entry that was read before the write.
    This avoids a round-trip that, against a replicated directory reached through a
    proxy, could hit a lagging replica and fail or return stale data.

    When the directory assigns the ID (GRAPH_LDAP_SERVER_UUID enabled), creates keep
    the existing read-back, since the generated ID cannot otherwise be recovered.

    #12618

  • Enhancement - Improve page structure on several pages: #12637

    We've added missing main and footer regions to several pages (404, private
    link resolving, missing config, logout, access denied, public link resolving)
    for a more consistent page structure. We've also fixed the "Skip to main" link,
    which previously did nothing on pages using the plain layout (login, logout,
    public/private link pages) due to a missing target id and a stale cached DOM
    reference.

    #12637

  • Enhancement - Show the select-all checkbox label in tile view: #12640

    The label of the select-all checkbox in the resource tiles view is now visible,
    improving the user experience by making it clear what the checkbox is for.

    #12640

  • Enhancement - Retry LDAP operations against a lagging replica: #12672

    The graph LDAP backend can now retry operations against a replicated directory
    where a write to the primary is followed by a read that lands on a replica which
    has not yet caught up. This covers the read-back that recovers a
    directory-assigned ID after a create (GRAPH_LDAP_SERVER_UUID enabled), which is
    retried until the entry becomes visible. The retry count and backoff are tunable
    through GRAPH_LDAP_RETRY_MAX_COUNT, GRAPH_LDAP_RETRY_BASE_DELAY and
    GRAPH_LDAP_RETRY_MAX_DELAY; the defaults keep the previous behaviour (a single
    immediate retry with no delay), so existing deployments are unaffected.

    Retries now distinguish reads from writes: a write is no longer retried on a
    network error, which can surface after the request was already sent and would
    otherwise apply the mutation twice.

    #12672

  • Enhancement - Add an opt-in bounded LDAP connection pool: #12688

    The auth-basic, users, groups and graph services can now be switched from a
    single long-lived reconnecting LDAP connection to a bounded pool of connections,
    so concurrent requests no longer serialize on one socket. Connections are dialed
    and bound lazily on checkout, unhealthy connections are discarded and lazily
    re-dialed rather than eagerly reconnected, and checkout blocks with a
    configurable timeout once the pool is exhausted.

    Pooling is off by default and fully backwards compatible. Enable it per service
    via 'OCIS_LDAP_POOL_ENABLED' (or the service-specific
    '_LDAP_POOL_ENABLED' override), and tune it with 'OCIS_LDAP_POOL_SIZE'
    (default 5) and 'OCIS_LDAP_POOL_CHECKOUT_TIMEOUT' (default 30s).

    The graph service's identity backend now shares the same LDAP client
    implementation used by the reva auth/user/group managers instead of maintaining
    its own separate reconnecting client.

    #12688

  • Enhancement - Bump dependencies: #12766

    Bumped Go and npm dependencies to address security findings:

    #12766