# fabias - Fabric Infrastructure and Security

[![PyPI version](https://badge.fury.io/py/fabias.svg)](https://badge.fury.io/py/fabias)
[![Documentation](https://img.shields.io/badge/docs-fabias.pages.dev-blue)](https://fabias.pages.dev)
[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

OneLake security and workspace automation for Microsoft Fabric. Works seamlessly both inside Fabric notebooks and as a standalone library.

## Why fabias?

Microsoft Fabric has no official Python SDK. The CLI is limited. fabias fills the gaps:

- **OneLake ABAC Security** - Table/row/column-level access control as code
- **Workspace Automation** - Create workspaces, assign roles, configure Spark
- **CI/CD Ready** - Works outside Fabric for GitHub Actions and automation scripts
- **Hybrid Runtime** - Same code runs in notebooks and standalone

## Installation

```bash
pip install fabias
```

## Quick Start

### Inside Microsoft Fabric

Authentication is automatic:

```python
import fabias

ws = fabias.workspace()  # Current workspace
pipeline = ws.pipeline("Daily ETL")
job = pipeline.run()
job.wait()
```

### Standalone Usage

```python
import fabias
from fabias import ServicePrincipalAuth

auth = ServicePrincipalAuth(
    tenant_id="your-tenant-id",
    client_id="your-client-id",
    client_secret="your-client-secret"
)
fabias.client(auth=auth)

ws = fabias.workspace("Analytics")
lakehouse = ws.lakehouse("Gold")
```

## OneLake Data Access Roles (ABAC Security)

The killer feature. Define lakehouse security as code:

```python
import fabias
from fabias import Role, Rule, EntraMember, FabricItem, ReadWrite, ItemAccess
from fabias import RowLevelSecurity, ColumnLevelSecurity

ws = fabias.workspace("Analytics")
lakehouse = ws.lakehouse("Sales")

# Regional managers: read-only with row filter
regional_role = Role(
    name="Regional Managers",
    rules=[
        Rule(
            path=["dbo.sales"],
            access=ReadWrite.READ,
            rls=RowLevelSecurity("region = 'West'")
        )
    ],
    members=[EntraMember("managers-group-guid")]
)

# Data engineers: full access inherited from workspace permissions
engineer_role = Role(
    name="Data Engineers",
    rules=[Rule(path=["*"], access=ReadWrite.READWRITE)],
    members=[FabricItem(access=[ItemAccess.READALL])]
)

# Apply roles
lakehouse.accessRoles.replace([regional_role, engineer_role])
```

## Workspace Operations

```python
import fabias

# List workspaces
for ws in fabias.workspaces():
    print(f"{ws.name}: {ws.id}")

# Create workspace
new_ws = fabias.workspaces.add("Feature Branch", capacity_id="...")

# Role assignments
new_ws.roleAssignments.add(
    principalId="spn-guid",
    principalType="ServicePrincipal",
    role="Admin"
)

# Access items
pipelines = ws.pipelines()
lakehouses = ws.lakehouses()
notebooks = ws.notebooks()
```

## Git Integration

```python
ws = fabias.workspace("GENESIS")

# Check status
status = ws.git.status()
print(f"Synced: {status.is_synced}")

# Pull from Git
if status.has_changes:
    ws.git.updateFromGit().wait()
```

## Connections

```python
# List connections
for conn in fabias.connections():
    print(f"{conn.name}: {conn.connectivity_type}")

# Manage access
conn = fabias.connection("SQL Server")
conn.roleAssignments.add(principalId="user-guid", principalType="User", role="Owner")
```

## Spark Settings

```python
ws = fabias.workspace("Analytics")

# Configure workspace Spark
settings = ws.spark.settings
settings.highConcurrency.enabled = True
settings.pool.starterPool.maxNodes = 10
settings.commit()
```

## Additional Modules

### Azure Data Factory

```python
from fabias.integrations import adf
from fabias import ServicePrincipalAuth

adf.client(
    subscription_id="...",
    resource_group="rg-name",
    factory="adf-name",
    auth=ServicePrincipalAuth(...)
)

job = adf.pipeline("ETL").run(date="2026-01-01")
job.wait()
```

### Key Vault Secrets

```python
from fabias.integrations import keyvault

# Inside Fabric (auth is automatic)
keyvault.client(vault_url="https://my-vault.vault.azure.net/")
password = keyvault.get("database-password")
```

### Teams Messaging

```python
from fabias.notifications import teams
from fabias.notifications.cards import Adaptive, TextBlock

teams.client(team_id="...", channel_id="...", auth=...)
teams.send(Adaptive(body=[TextBlock("Deployment complete!")]))
```

## Authentication Methods

| Method | Use Case |
|--------|----------|
| Automatic | Inside Fabric notebooks |
| `ServicePrincipalAuth` | CI/CD, automation scripts |
| Environment variables | `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET` |
| From Key Vault | Bootstrap from secrets |

## Requirements

- Python 3.9+
- `requests`
- Inside Fabric: `notebookutils` (pre-installed)

## License

MIT
