Argus: Self-Service Data Access

Build auditable, self-service data access with Databricks Apps and Unity Catalog while keeping privileged enforcement controlled.

Key Takeaways:

Governance and security icon
Decentralize decisions, not control. Let data owners approve access while privileged enforcement stays centralized.
Audit visibility icon
Make every access decision auditable. Preserve the requester, owner, business justification, approval, and outcome.
Self-service access icon
Turn governance into self-service. Give users a clear access path without making platform engineers the permission queue.

Granting access to data is technically simple. A single GRANT statement may be enough to give a user or group permission to query a table. Governing that decision across a growing organization, however, is considerably more difficult.

As companies become more data-driven, their metastores expand alongside the number of users, teams, and data products they support. Without clear ownership and an auditable process, permission management fragments and the consequences extend beyond security and compliance. When an organization cannot easily determine who has access to its data, why that access was granted, who approved it, or even who owns the underlying asset, governance itself becomes an operational bottleneck: data consumers wait for access, data owners remain disconnected from decisions about their own assets, and platform engineers spend time coordinating permissions instead of improving the platform.

Effective governance is not about ruling a metastore with an iron fist. It is about establishing guardrails that allow the right people to make access decisions without sacrificing security, accountability, or productivity. This is the challenge Argus was designed to address.

Access Control Is More Than GRANT and REVOKE

Granting a permission is generally the final technical step of an access-request process. Before that command can be executed, a consumer must identify the required dataset, determine who owns it, select the appropriate principal and level of access, explain the business need, obtain authorization, and wait for the permission to be applied. Although the resulting GRANT may take only seconds, everything leading up to it can leave users blocked for days.

Without a defined workflow, these requests become scattered across private messages, emails, and ticketing systems. Even when the correct owner is eventually found and the permission is granted, the business decision may remain hidden inside a conversation. Unity Catalog audit logs can show which privilege changed, who performed the action, and when it occurred, but a direct permission event does not necessarily preserve the complete justification and approval context. Reconstructing the decision can therefore require information from several systems.

Many organizations respond by centralizing every request within the Data Platform team. This can provide consistency in smaller environments, but it becomes increasingly difficult to sustain as the number of teams, datasets, and requests grows. Platform engineers become the operational queue for the entire metastore locating owners, validating approvals, executing repetitive changes, and answering status questions while consumers wait. The problem is not the performance of an individual engineer; it is a process that depends on a small group to coordinate every decision and execute every change.

Data owners are better positioned to decide whether access is appropriate, while the Data Platform team is better positioned to define how approved access should be enforced safely. A scalable process should therefore decentralize access decisions while preserving centralized, controlled enforcement.

Unity Catalog, Native Access Requests, and a Moving Platform

Unity Catalog provides the foundation for this model. It centralizes ownership and access control across catalogs, schemas, tables, and other securable objects while supporting users, groups, and service principals as principals. Privileges granted at the catalog or schema level can inherit to child objects, and ownership provides a clear way to assign responsibility for governed resources. Combined with audit logs, these capabilities provide both an enforcement layer and a record of how access is administered.

Unity Catalog has also expanded beyond these foundational controls. Its native Request for Access feature allows consumers to request privileges from Catalog Explorer, notebooks, the SQL editor, AI/BI dashboards, and Genie. Requests can be routed through email, Slack, Microsoft Teams, webhooks, or redirect URLs. The workflow can also resolve configured destinations, validate prerequisite privileges such as USE CATALOG and USE SCHEMA, and allow authorized users to grant privileges directly or add the requester to an existing group.

The timing of this functionality matters. Self-service access-request destinations entered Public Preview in August 2025, while metastore-level enablement, inherited destinations, and broader owner-based routing arrived in June 2026. The native workflow was not a static baseline: it continued evolving while custom solutions to the same organizational problem were being designed and developed. This convergence validates the problem by showing that access discovery, routing, approval, and auditability have become first-class Unity Catalog concerns.

For organizations whose requirements are satisfied by the native workflow, Request for Access should be the default choice. It is integrated into the platform and avoids the cost of maintaining a custom application. Other organizations, however, may require ownership of the operational request data, custom access abstractions, organization-specific lifecycle states, controlled processing schedules, specialized notification rules, or separation between recording approval and executing privileged changes. Unity Catalog supports this extensibility through webhooks and redirect destinations for external access-management systems.

The arrival of these native capabilities changed the position of Argus, but not the problem it was designed to solve. Rather than replacing Unity Catalog's access-request functionality, Argus demonstrates how an organization can build an opinionated and extensible governance workflow around Unity Catalog when its operational requirements extend beyond the native path.

Argus: An Owner-Driven Access Workflow

Argus is a data access portal built natively on Databricks to transform Unity Catalog permission changes into a structured, owner-driven workflow. Through a Databricks App, consumers can select the resources they need, request access on behalf of a group, and provide the business context behind the request. Argus identifies the relevant data owner, routes the request for review, and records its status and resulting decision in a Delta table governed by Unity Catalog.

Once a request is approved, the application does not apply the permission directly. A separate Databricks Workflow processes approved requests and executes the corresponding GRANT or REVOKE statements, so Unity Catalog remains the source of truth for enforcement while Argus manages the organizational process surrounding it.

From Request to Enforcement

Argus begins by identifying the signed-in user through Databricks Apps. The requester's email is populated automatically, and the group selector is limited to groups to which that user belongs. This keeps the consumer experience focused on the identities they can legitimately represent.

The consumer selects a catalog and, when needed, a schema or table; chooses GRANT or REVOKE; selects an application-level READ, EDIT, or MANAGE access profile; and provides a business justification. The platform team controls how those profiles map to Unity Catalog privileges. Argus resolves the owner of each resource and lets the consumer stage several objects before submission. Although the objects are submitted together, Argus persists one request row per object so that different owners can review their portions independently.

Figure 1. Argus separates request, approval, and enforcement while preserving alternative outcomes.

Figure 2. A consumer stages multiple GRANT and REVOKE operations in the Request Access module.

At submission, each row enters PENDING and Argus notifies the resolved owner through the configured Slack, Microsoft Teams, or email route. The permission_request table preserves the object path, target group, request type, requested access profile, requester, owner, justification, timestamp, and current status.

Figure 3. The resolved data owner receives a notification when a request is submitted.

A request appears in Pending Approvals for users authorized to manage the target resource. An owner or another authorized manager can approve or reject it and may record a decision comment. The requester can also cancel a pending request that is no longer needed. Approval changes the request to APPROVED; it does not immediately modify Unity Catalog. Because enforcement is deferred to the scheduled run, this window is also reversible: the requester or an authorized manager can still cancel an approved request that has not yet been processed, moving it to CANCELLED before any privilege changes.

Figure 4. Owners and other authorized managers review requests for resources they manage.

A scheduled Databricks Workflow reads APPROVED rows, translates their access profiles into the corresponding Unity Catalog GRANT or REVOKE statements, and, after successful execution, marks each request PROCESSED and records its processing time.

Throughout the lifecycle, consumers use My Requests to view pending, approved, rejected, cancelled, and processed requests together with any decision comments. Authorized managers can also register pre-approved changes through Manage Permissions; Argus records those changes as approved and routes them through the same controlled processing path. The Data Platform team defines the profiles, schedule, and execution guardrails, while auditors can query the operational history alongside Unity Catalog audit logs.

Figure 5. Consumers track request outcomes and decision history in My Requests.



Together, the request form, approval queue, operational table, and processing workflow create a traceable chain from business justification to effective permissions in Unity Catalog.

Inside Argus: Identity, State, and Execution Boundaries

Argus is intentionally split across three execution boundaries: an interactive Databricks App, an operational Delta table, and a privileged Databricks Workflow. The application authenticates users, resolves metadata, collects requests, and records decisions. The request table persists the lifecycle of each operation, while the workflow is the only component that translates approved intent into Unity Catalog permissions. This is a security boundary as much as an architectural one: the component exposed to users does not need the authority required to change permissions across the governed data estate.

Figure 6. Argus separates user interaction, operational state, and privileged Unity Catalog enforcement.

Identity and Authorization

Databricks Apps supports two complementary authorization models: the application's own identity and the identity of the user interacting with it. Argus uses both for different purposes. The service principal created for the app accesses the attached SQL warehouse and the operational request data. A separate workflow identity reads approved requests and performs the corresponding permission changes.

The application identity should receive only the privileges required to operate the portal: CAN USE on its SQL warehouse, USE CATALOG and USE SCHEMA on the governance namespace, and SELECT and MODIFY on the request table. The workflow identity needs the same operational-table access together with MANAGE and the required parent usage privileges on the Unity Catalog scopes governed by Argus. Making that identity a metastore administrator is convenient, but unnecessarily broad for most production deployments; catalog-scoped authority provides a safer default boundary.

Resolving the Current User with On-Behalf-of-User Authorization

Within the interactive application, Argus uses Databricks on-behalf-of-user (OBO) authorization. Databricks forwards the caller's email and access token in the request headers, and Argus uses that token to resolve the caller's own group membership and administrator status. The resulting identity is used to restrict the group selector, scope resource discovery, and show approval records relevant to that caller.

# app.py
def _current_identity() -> tuple[str, list[str], bool]:
    # flask.g is scoped to the current HTTP request, preventing repeated
    # identity lookups without sharing identity data between requests.
    cached = getattr(flask_g, "_identity", None)
    if cached is not None:
        return cached

    # Databricks Apps forwards the authenticated user's identity and access
    # token. The email supports attribution, while the token is used for
    # caller-scoped authorization checks.
    email = flask_request.headers.get("X-Forwarded-Email", "")
    token = flask_request.headers.get("X-Forwarded-Access-Token", "")

    groups, is_admin = db.get_identity_obo(token)
    flask_g._identity = (email, groups, is_admin)
    return flask_g._identity


# db.py
def _user_client(user_token: str) -> WorkspaceClient:
    # Bind SDK calls to the caller's forwarded token instead of the
    # application's service-principal identity.
    return WorkspaceClient(
        host=w.config.host,
        token=user_token,
        auth_type="pat",
    )


def get_identity_obo(user_token: str) -> tuple[list[str], bool]:
    # Missing identity context cannot grant elevated access.
    if not user_token:
        return [], False

    try:
        # Resolve the current user through the caller-scoped SDK client.
        me = _user_client(user_token).current_user.me()

        # Normalize group names before using them in authorization decisions.
        groups = sorted(
            group.display
            for group in (me.groups or [])
            if group.display
        )

        # Workspace administrators retain the application's administrative path.
        is_admin = any(group.lower() == "admins" for group in groups)
        return groups, is_admin

    except Exception:
        # Identity-resolution failures fail closed: no groups and no
        # administrative privileges are inferred.
        return [], False

Listing 1. The OBO path from Databricks request headers to a user-scoped SDK client and authorization context.

The explicit auth_type is important. The Databricks App runtime already exposes OAuth credentials for the application service principal; constructing a second SDK client without selecting an authentication method can make the SDK detect both the ambient application credentials and the forwarded user token. Argus therefore forces bearer-token authentication for this client so the call executes as the user. Successful lookups are cached briefly to avoid repeating current_user.me() throughout an interaction.

Two shortcuts in this path are deliberate but worth naming: administrator status is derived from a group display name rather than a stable identifier, and a failed identity lookup returns an empty context without logging. Both fail closed, which is the safe direction, but neither is observable.

The resolved identity is not used only to personalize the interface. Before the management module reads grants or registers a pre-approved change, the callback verifies that the caller is an administrator, owns the securable, or holds MANAGE or ALL PRIVILEGES directly or through one of their groups. A failed check stops the action before a request row is written.

# app.py

# Resolve the caller's identity and group memberships once per request.
email, user_groups, is_admin = _current_identity()
token = _obo_token()

# Re-evaluate authorization on the server at the moment of the action.
# UI visibility is not treated as an authorization boundary.
if not db.user_can_manage_obo(
    token,
    email,
    user_groups,
    is_admin,
    object_type,
    catalog,
    schema,
    table,
):
    return dbc.Alert(
        "You don't have MANAGE on this object.",
        color="danger",
    )

Listing 2. The management path is gated by the caller's effective Unity Catalog authority.

The Request Table as a State Machine

The permission_request Delta table is the operational contract between the application and the workflow. The app creates one PENDING row for each requested object. An authorized manager changes that row to APPROVED or REJECTED, while the requester can move an obsolete request to CANCELLED. The workflow consumes only APPROVED rows and moves successfully enforced changes to PROCESSED; until that run occurs, an APPROVED row can still be cancelled by the requester or an authorized manager. Pre-approved changes submitted through Manage Permissions enter the same path at APPROVED rather than bypassing the table.

Each row represents one requested change against one Unity Catalog object and carries the context needed to reconstruct the decision: the catalog, schema or table, target group, owner, requester, request type, access profile, justification, decision comment, deciding identity, status, and lifecycle timestamps. The state transition is therefore the control boundary between intent and enforcement: approval records that a change is authorized, while PROCESSED records that the workflow has applied and verified it.

-- Stores one operational record for each requested securable object.
CREATE TABLE IF NOT EXISTS IDENTIFIER(
    :catalog_name || '.permissions.permission_request'
)
(
    -- Stable identifier used to correlate submission, decision,
    -- enforcement, and auditing events.
    request_id             INT       NOT NULL,

    -- Nullable path components encode the target scope:
    -- catalog only, catalog.schema, or catalog.schema.table.
    `catalog`              STRING,
    `schema`               STRING,
    `table`                STRING,

    -- Approval authority resolved when the request is submitted.
    data_owner             STRING    NOT NULL,

    -- Group that will receive or lose the requested privileges.
    `group`                STRING    NOT NULL,

    -- Request payload and business context captured at submission.
    requested_by           STRING    NOT NULL,
    requested_at           TIMESTAMP NOT NULL,
    request_type           STRING    NOT NULL,
    requested_permissions  STRING    NOT NULL,
    requester_comment      STRING,

    -- Lifecycle state consumed by both the application and the
    -- permission-processing workflow.
    request_status         STRING,

    -- Decision metadata populated when the request is reviewed.
    decision_comment       STRING,
    decided_by             STRING,

    -- Written only after the requested change has been executed
    -- and verified by the enforcement workflow.
    processed_at           TIMESTAMP,

    -- Unity Catalog primary keys are informational rather than enforced;
    -- the application must therefore preserve request_id uniqueness.
    CONSTRAINT pk_permission_request PRIMARY KEY (request_id)
)
COMMENT 'Tracks data access permission requests across objects'

Listing 3. The Delta table that joins request context, authorization state, and processing outcome.

Request identifiers are assigned at submission by reading the current maximum request_id and incrementing it. This is simple and sufficient for the portal's write pattern, where submissions arrive through a single application at human speed, but it is not safe under truly concurrent writers; migrating to a Delta identity column is a straightforward hardening step.

Privilege Abstraction and Enforcement

A self-service access workflow is not truly self-service if consumers must understand Unity Catalog's entire privilege graph before they can submit a request. A table-level SELECT grant is unusable without USE CATALOG and USE SCHEMA on its parent objects. Editing data can require MODIFY in addition to read and traversal privileges, while catalog- and schema-level workflows may require creation, refresh, volume, model, or function privileges. Requiring every consumer to assemble that set manually would reproduce the same complexity that the portal is intended to remove.

Argus therefore exposes three application-level access profiles: READ, EDIT, and MANAGE. These are not new Unity Catalog privileges. They are deterministic bundles maintained by the Data Platform team and expanded according to whether the target is a catalog, schema, or table. The consumer selects an intent; the enforcement layer remains responsible for translating that intent into platform-specific privileges.

# Translates Argus's user-facing permission profiles into the concrete
# Unity Catalog privileges applied at each supported object level.

## Traversal prerequisites for child objects, such as USE CATALOG and
# USE SCHEMA, are generated separately by the enforcement workflow.
ROLE_PRIVILEGE_MAP = {
    # READ permits data consumption without modification.
    PermissionRole.READ: {
        "CATALOG": [
            "USE CATALOG", "BROWSE",
            "EXECUTE", "READ VOLUME", "SELECT",
        ],
        "SCHEMA": [
            "USE SCHEMA",
            "EXECUTE", "READ VOLUME", "SELECT",
        ],
        "TABLE": [
            "SELECT",
        ],
    },
    # EDIT extends consumption with the privileges required to modify
    # existing data and create objects appropriate to the selected scope.
    PermissionRole.EDIT: {
        "CATALOG": [
            "USE CATALOG", "USE SCHEMA", "APPLY TAG", "BROWSE",
            "EXECUTE", "READ VOLUME", "SELECT",
            "MODIFY", "REFRESH", "WRITE VOLUME",
            "CREATE FUNCTION", "CREATE MATERIALIZED VIEW", "CREATE MODEL",
            "CREATE MODEL VERSION", "CREATE SCHEMA", "CREATE TABLE",
            "CREATE VOLUME",
        ],
        "SCHEMA": [
            "USE SCHEMA", "APPLY TAG",
            "EXECUTE", "READ VOLUME", "SELECT",
            "MODIFY", "REFRESH", "WRITE VOLUME",
            "CREATE FUNCTION", "CREATE MATERIALIZED VIEW", "CREATE MODEL",
            "CREATE MODEL VERSION", "CREATE TABLE", "CREATE VOLUME",
        ],
        "TABLE": [
            "APPLY TAG", "MODIFY", "SELECT",
        ],
    },

    # MANAGE combines operational access with delegated privilege
    # administration. ALL PRIVILEGES does not include Unity Catalog's
    # native MANAGE privilege, so both are granted explicitly.
    PermissionRole.MANAGE: {
        "CATALOG": ["ALL PRIVILEGES", "MANAGE"],
        "SCHEMA":  ["ALL PRIVILEGES", "MANAGE"],
        "TABLE":   ["ALL PRIVILEGES", "MANAGE"],
    },
}

Listing 4. Permission Matrix Definition in the permission_grant.py notebook

For schema- and table-level requests, the SQL builder emits traversal prerequisites before the object-level grant. The function does not first query whether the principal already has them: repeated GRANT statements are idempotent, which keeps SQL generation deterministic and avoids an additional read before execution. The interpolated identifiers in these statements are not free-form input: the application populates catalog, schema, and table names from metastore enumeration, and the group from the caller's own memberships, so the enforcement layer only ever sees names that exist in Unity Catalog. Validating identifiers against the metastore again at enforcement time remains a worthwhile defense-in-depth step.

Figure 7. Argus privilege resolution and grant expansion.

The revoke builder follows a deliberately narrower rule: it removes the mapped privileges from the requested object but does not remove parent-level USE CATALOG or USE SCHEMA grants. Those prerequisites may still be required to reach other resources. This also means that an object-level revoke cannot negate access inherited from a parent catalog or schema; inherited access must be changed at the level where it was granted. A related consequence is that profiles overlap: READ's privileges are a subset of EDIT's, so revoking one profile removes privileges the other may still legitimately cover. Revoking EDIT from a group that also holds an approved READ removes SELECT along with the editing privileges; restoring the intended state requires re-granting the remaining profile. Profile-aware revocation subtracting only the privileges not covered by another active grant is a candidate refinement for the enforcement layer.

Enforcement is performed only for rows in APPROVED state. The notebook builds the appropriate statements, executes them sequentially through spark.sql(), and verifies the resulting state with SHOW GRANTS. Grant verification checks both the target privileges and its traversal prerequisites. Revoke verification confirms that the mapped target privileges are absent.

# permission_grant.py

# Materialize the approved control-plane queue for serial processing.
# This assumes the number of approved requests in each run remains bounded.
approved = (
    spark.table(TARGET_TABLE)
        .filter(
            col("request_status")
            == RequestStatus.APPROVED.value
        )
        .collect()
)

# A request is only added here after its resulting privileges are verified.
processed_ids = []

for row in approved:
    try:
        request_type = RequestType(row["request_type"])

        # Translate the approved request into one or more Unity Catalog
        # statements, including any required traversal privileges.
        sqls = (
            build_grant_sql(row)
            if request_type == RequestType.GRANT
            else build_revoke_sql(row)
        )

        # Execute every statement belonging to the current request before
        # attempting to advance its lifecycle state.
        for sql in sqls:
            print(f"[BATCH] Executing: {sql}")
            spark.sql(sql)

        # Verify the resulting Unity Catalog state rather than treating
        # successful SQL submission as sufficient proof of enforcement.
        verified = (
            verify_grant(row)
            if request_type == RequestType.GRANT
            else verify_revoke(row)
        )

        if verified:
            processed_ids.append(row["request_id"])

    except Exception as e:
        # Isolate failures to the current request. Because its state remains
        # APPROVED, the workflow can safely attempt it again on the next run.
        print(
            f"[BATCH] Error on request_id={row['request_id']}: "
            f"{e} — will retry next run."
        )

if processed_ids:
    # Advance only successfully verified requests. Updating them together
    # reduces lifecycle-table writes without coupling their SQL execution.
    ids = ", ".join(str(request_id) for request_id in processed_ids)

    spark.sql(f"""
        UPDATE {TARGET_TABLE}
        SET request_status = '{RequestStatus.PROCESSED.value}',
            processed_at = current_timestamp()
        WHERE request_id IN ({ids})
    """)

Listing 5. Request Processing in the permission_grant.py notebook

Only requests that pass verification are included in the final bulk update to PROCESSED. An exception or failed verification leaves the row in APPROVED, allowing the next scheduled run to retry it. This produces an at-least-once processing model: SQL generation must be safe to repeat, and verification determines whether the lifecycle can advance.

Deploying Argus with Declarative Automation Bundles

Argus is packaged as a single Databricks Declarative Automation Bundle, formerly known as a Databricks Asset Bundle. The bundle defines the application and its enforcement workflow as version-controlled resources while allowing environment-specific values to be supplied for sandbox and production targets. Its value is not simply reducing deployment steps; it makes the separation between user interaction and privileged execution reproducible.

The bundle deploys two independently secured runtime components. The Databricks App hosts the request, approval, management, and tracking interfaces and connects to its SQL warehouse with CAN USE. The permission-processing workflow runs separately and is the only component authorized to translate approved requests into Unity Catalog changes. Packaging both components together ensures that the application source, workflow definition, schedule, runtime parameters, warehouse attachment, and execution identities evolve as a consistent deployment unit without giving both components the same authority.

Each deployment target supplies the governance catalog, fully qualified request-table name, SQL warehouse ID, application name, and workflow service principal. Optional configuration controls the processing schedule, time zone, paused state, and notification routing through Slack, Microsoft Teams, email, or multiple channels. The processing task uses serverless notebook compute where available because no cluster is declared in its resource definition.

That service principal requires USE CATALOG and USE SCHEMA on the operational table’s parent catalog and schema, together with SELECT and MODIFY on the table itself. It also requires ownership or MANAGE only on the Unity Catalog scopes that Argus is permitted to change.A sandbox target may run as the deployer for development convenience, but that behavior should not be carried into production.

Figure 8. Successful deployment of Argus to the sandbox bundle target.

After deployment, the workspace exposes the two expected resources: the data-access portal and the scheduled permission-processing job.

Figure 9. Bundle resources created for the Argus application and permission-processing workflow.

One implementation constraint remains in the current deployment. The repository retains app.yml as a runtime configuration fallback because the tested CLI version did not reliably propagate the bundle’s inline application environment. Until generated application configuration is validated, deployment variables and the runtime file must be maintained consistently. Resolving that duplication is a production-hardening task, but it does not change the separation between application and enforcement identities.

Operational Outcomes

Argus turns a fragmented process into a shared operational record. Requests, justifications, owners, decisions, comments, lifecycle states, and processing timestamps are stored in a governed Delta table. Consumers follow their requests through My Requests without contacting the Data Platform team for status updates, while data owners make decisions for resources whose purpose and sensitivity they understand. Pre-approved changes registered through the management module enter the same processing and auditing lifecycle, so changes initiated outside the standard request path remain visible.

The result is a clearer separation of responsibilities. Data owners determine whether access is appropriate. The Data Platform team defines the available access profiles, their underlying Unity Catalog privileges, the execution schedule, and the identities authorized to enforce changes. Auditors can query the resulting operational history and correlate the business decision recorded by Argus with the permission event recorded in Unity Catalog audit logs.

Limitations and Next Steps

Argus currently records that access was granted, but not for how long it should remain valid. Grants have no expiration date, and there is no recertification cycle prompting owners to periodically reconfirm that existing access is still appropriate. For a workflow whose purpose is auditability, this is the most significant gap: the operational table can answer who received access, why, and who approved it, but not whether that access should still exist today. Introducing time-bound grants an optional expiry recorded at approval and enforced by the same scheduled workflow through a corresponding REVOKE and owner-driven access reviews are therefore naturally the next directions for future development.

Argus also supports access requests only for groups, not individual users. A future module could introduce user-level requests when this functionality is enabled by the application manager.

The application's configuration parameters require further refinement as well. Integrating Databricks Secrets would provide more secure handling of sensitive configuration values and establish a stronger foundation for future development. Operational hardening is also planned, most importantly structured logging and alerting so that a failed enforcement attempt is surfaced rather than silently retried.

Additional capabilities under consideration include managing PII and PHI masking policies and row-level access through Argus, further expanding the application as a permission-management system. Using the application interface to support contributions to a Data Dictionary is another potential direction.

Conclusion

A GRANT or REVOKE statement is only the final technical action in an access-management process. The greater challenge is ensuring that the decision behind it has a clear requester, an appropriate owner, sufficient business context, a controlled execution path, and an auditable outcome. Argus brings those requirements together with capabilities already available within the Databricks platform: a Databricks App for requesting and reviewing access, a governed Delta table for the operational history, application-level profiles that abstract Unity Catalog's privilege graph, and a separate workflow that applies approved changes through a controlled identity an opinionated operational process built around Unity Catalog's ownership, privilege, and auditing foundations rather than a replacement for them.

More broadly, the architecture shows that decentralizing access decisions does not require decentralizing privileged execution. The final permission change may still be a GRANT or REVOKE statement, but governance is the process that makes that statement explainable, auditable, and defensible.

Covering 100% of U.S. time zones, becoming a natural extension of your team

Elite engineers ready for flexibility, scalability, and measurable impact.
Build IP that belongs to you
Proven work with the Fortune 500
Start Building
Start Building

Continue Reading

AI Development Governance
Govern AI before it scales
Powering Growth With Unified Data
One Platform for Analytics and AI
AI Governance Advantage
Governance powers production AI