# Permissions Log Viewer

A Streamlit application for viewing and analyzing audit logs of user permissions and access changes in Neo4j by tracking CDC events.

Note: This is not the ideal approach for implementing an audit log. Until we have a better solution that explicitly tracks changes in assignments and permissions made to users, this serves as a workaround.

Not all changes originate from the Settings app, so one advantage of this approach is that it tracks ALL permission changes in Neo4j—whether from the frontend, database PRs, or Lambda/Step Function workflows. 

## 🚀 Live Application

**[Access the App in Snowflake →](https://app.snowflake.com/sme/orchard/#/streamlit-apps/DEV_ENGINEERING.PUBLIC.VB1J1R3V7AN1I_TY)**

## Overview

This application tracks permission access changes for Profiles, using distinct SQL queries.
The relationships tracked include:
* HAS_ACCESS_TO
* HAS_ADMIN_ACCESS_TO
* DELETED_HAS_ACCESS_TO
* DELETED_HAS_ADMIN_ACCESS_TO

## Features

- **Identity Search**: Query by Identity ID (UUID format) or Email address
- **Display**: View all events operations, in chronological order
- **Filtering**: Filter by tenant, operation type, profile type, relationship type, and date range
- **Visualizations**: Timeline charts, operation counts, profile distribution
- **Detailed Event View**: Examine details of CDC events
- **CSV Export**: Download filtered results for further analysis

## Quick Start

### Development Setup

```bash
# Initialize UV environment
make init

# Or manually:
uv venv
uv pip install -e ".[dev]"
```

### Code Checks

```bash
# Format code
make fmt

# Lint code
make lint

# Fix linting issues
make lint-fix

# Type checking
make type-check

# Run all checks
make check
```


### Query Flow

```
Identity UUID or Email
    ↓
[Email Resolution] If email provided, resolve to UUID via FACT.PROD.IDENTITY
    ↓
[Step 1] Load identity from FACT.PROD.IDENTITY
    ↓
[Step 2a] Load profiles from CDC_MUSICGRAPH_HASPROFILE
    ↓
[Step 2b] Hydrate profile identifiers from FACT.PROD.PROFILE
    ↓
[Step 2c] Load additional profiles from FACTS.PROD.HAS_PROFILE (not in CDC)
    ↓
[Step 3] Query access tables in parallel:
    ├─ HAS_ACCESS_TO
    ├─ HAS_ADMIN_ACCESS_TO
    ├─ DELETED_HAS_ACCESS_TO (+ enrichment)
    └─ DELETED_HAS_ADMIN_ACCESS_TO (+ enrichment)
    ↓
[Step 4] Hydrate tenant metadata (Vendors, Subaccounts, Collaborators, LabelParticipants)
    ↓
[Step 5] Combine & sort results
```

## Data Sources

The application queries these Snowflake tables:

- `FACT.PROD.IDENTITY`: User identity information and email-to-UUID resolution
- `FACT.PROD.HAS_PROFILE`: Identity-to-profile relationships (canonical source)
- `CDC_MUSICGRAPH_HASPROFILE`: Identity-to-profile relationships (CDC events)
- `CDC_MUSICGRAPH_HASACCESSTO`: Profile access
- `CDC_MUSICGRAPH_HASADMINACCESSTO`: Settings access
- `CDC_MUSICGRAPH_DELETEDHASACCESSTO`: Deleted access
- `CDC_MUSICGRAPH_DELETEDHASADMINACCESSTO`: Deleted Settings access
- `FACT.PROD.PROFILE`: Profile metadata (for profile hydration)
- `ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.VENDOR`: For Vendor metadata
- `ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.SUBACCOUNT`: For Subaccount metadata
- `ORCHARD_APP_REPORTING_V2.PROD_OWS_COLLABORATOR_OWS_COLLABORATOR.COLLABORATOR`: For Collaborator metadata
- `FACTS.PROD.LABEL_PARTICIPANT`: LabelParticipant metadata
