databrickslabs / databrickslabs/ontos

[FEATURE]: Background sweep to auto-expire/revoke access grants on expiry (wire up check_and_process_expirations)

Open
#682 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

scope/entitlement tech/python type/feature
Dominant language
Python
Stars
212
Forks
71
Avg merge
4d 10h
Merged PRs (30d)
43

Description

Is there an existing issue for this?

  • I have searched the existing issues (no dedicated issue exists; fits under epic #12 Entitlement Management, depends on #16 background-job infra, analogous to #119)

Problem statement

Access grants carry an expiry but are never actually expired or revoked when that time passes. The scaffolding exists but is dead code:

  • access_grants.expires_at is NOT NULL and indexed (set at approval to now() + granted_duration_days).
  • AccessGrantStatus enum defines ACTIVE / EXPIRED / REVOKED.
  • Repository methods get_expired() and mark_expired() are implemented.
  • Manager method check_and_process_expirations() is implemented, with a docstring stating "This should be called by a background job."

The gap: check_and_process_expirations() has zero call sites (not in startup_tasks.py, app.py, routes, or any thread). So when a grant's expires_at passes, the row stays status='active' in the DB and nothing is revoked on the Databricks/UC side — it only disappears from the UI because active-grant queries filter expires_at > now() at read time. Stale grants therefore persist server-side indefinitely.

Proposed Solution

Wire check_and_process_expirations() into a periodic background sweep, reusing the existing in-process pattern (JobsManager.start_background_polling(), a threading.Thread registered in startup_tasks.py). Expected touch: register the sweep thread in startup_tasks.py, add a configurable interval in config.py, and call the existing manager method. No DB migration needed.

Design decision for maintainer input (the reason to discuss before coding): mark_expired() currently only flips status to EXPIRED — it does not revoke the underlying UC permission. Two scope options:

  • (A) Label-only: sweep marks expired grants EXPIRED (minimal, matches current mark_expired() behavior).
  • (B) True revocation: sweep also revokes the actual Databricks/UC permission via GrantManager/DeliveryService and sets REVOKED.

Please advise which scope is desired.

How to test:

  • Create/approve a grant with a short duration; advance past expires_at.
  • Confirm the sweep flips status to EXPIRED (option A) and, if in scope, that the UC permission is actually revoked (option B).
  • Confirm the interval is configurable and the thread registers cleanly at startup without disrupting existing background polling.

Additional Context

Conceptually a sub-task of epic #12 (Entitlement Management), which explicitly calls for "a lifecycle around" grants/revocation. Depends on the job infrastructure tracked in #16 (Complete background job feature). Analogous prior pattern: #119 (Genie grace-period deactivation via background job). Sibling lifecycle gap: #311 (approved requests don't actually grant).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with startup_tasks.py, config.py, JobsManager.start_background_polling(), and the existing check_and_process_expirations() method. Confirm the intended scope with the maintainer—label-only expiry or true UC revocation—then test a short-duration grant, configurable interval, and clean startup registration without disrupting existing polling.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
authorization, backend, cloud
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.