Setup: tenant settings, identity, and provisioning¶
Do these once, in order, before running the collector.
1. Fabric / Power BI tenant settings (Admin portal)¶
| Setting | Where | Why |
|---|---|---|
| Fabric data agent | Admin portal → Tenant settings | Allows FDA to exist/run |
| Power BI semantic models via XMLA endpoints | Tenant settings → Integration | NL2DAX executes over XMLA |
| Cross-geo processing / storing for AI | Tenant settings → AI and Copilot | Required by FDA |
| Allow Microsoft Purview to secure AI interactions | Tenant settings → Information protection | Enables FDA audit/DSPM capture (preview) |
| Service principals can use Fabric APIs | Tenant settings → Developer settings | Collector SP calls Fabric/Kusto |
2. Workspace monitoring (the GA DAX source)¶
On the workspace that hosts the semantic model the FDA queries:
- Workspace → Settings → Monitoring → Enable. This provisions a read-only monitoring Eventhouse (KQL DB).
- Confirm the
SemanticModelLogstable populates (ask a question through the FDA, then query it). - Note the monitoring KQL database Query URI — the collector reads executed DAX from here.
You may host the observability tables in this same Eventhouse or a dedicated one. A dedicated observability Eventhouse is recommended so retention/permissions are independent of the monitoring store.
3. Provision the observability Eventhouse¶
- In your observability workspace: + New item → Eventhouse, name it e.g.
FDA_Observability_EH. - Open its KQL database, note the Query URI (looks like
https://<cluster>.<region>.kusto.fabric.microsoft.com+ database name). The WinForms app and collector both use it. - Run
fabric/kql/01_tables.kql, thenfabric/kql/02_policies.kqlin the query editor.
4. Register the collector app (Entra ID)¶
Create one app registration, e.g. FDA-Observability-Collector.
API permissions (application, admin-consented):
| API | Permission | Purpose |
|---|---|---|
| Microsoft Graph | AiEnterpriseInteraction.Read.All |
Export Copilot prompt/response text |
| Microsoft Graph | GroupMember.Read.All |
Expand FDA_USER_GROUP_ID into the per-user Graph export set (only if using group expansion) |
| Office 365 Management APIs | ActivityFeed.Read |
Pull CopilotInteraction audit records |
| (Power BI Service) | Tenant.Read.All (optional) |
Resolve workspace/model names |
Fabric data-plane access: add the app's service principal as Member/Contributor on the observability
workspace so it can ingest into the Eventhouse, and grant it Database Ingestor + Database Viewer on the
KQL database. Database Ingestor is what lets the collector use queued ingestion (USE_QUEUED_INGESTION=True,
the default — it streams via the DM endpoint https://ingest-<cluster>… and scales to large batches). Also grant
Viewer on the monitoring KQL database (to read executed DAX).
Choosing the Graph user set: set
FDA_USERSto an explicit UPN list, or setFDA_USER_GROUP_IDto an Entra group object id and the collector expands its transitive members automatically (de-duplicated, paged). If both are set they are merged. Put your FDA end users in a security group and point the collector at it so the set stays current without redeploying the notebook.
Create a client secret (or, preferred, a certificate) and store it in the workspace's Key Vault-backed connection or a Fabric notebook secret. Never hardcode it.
5. Office 365 Management API subscription¶
The audit content feed must be subscribed once per content type. The collector calls
POST .../subscriptions/start?contentType=Audit.General automatically on first run, but the SP needs
ActivityFeed.Read. Verify the tenant's unified audit log is turned on (Purview → Audit).
6. WinForms app identity¶
The review app uses interactive AAD (the reviewer's own identity) via MSAL — no secret on the client. Register a second public client app, e.g. FDA-Observability-Review, with:
- Platform: Mobile and desktop, redirect URI
http://localhost(andhttps://login.microsoftonline.com/common/oauth2/nativeclient). - Delegated permission: the Kusto/Fabric scope
https://kusto.fabric.microsoft.com/user_impersonation(the app requestshttps://<cluster>.kusto.fabric.microsoft.com/.defaultat runtime). - Reviewers must have Viewer on the observability KQL database.
Record the Client ID and Tenant ID; you enter them in the app's Configuration dialog (or appsettings.json).
7. Quick verification¶
# After schema + collector run, in the KQL query editor:
FdaInteractions | take 50
FdaInteractions | summarize count() by MatchConfidence, bin(Timestamp, 1h)
If FdaInteractions has rows with GeneratedDax populated and MatchConfidence != "Unmatched", the pipeline works.