Skip to main content

Quick start guides

This document is for a new user sitting at the keyboard with the demo environment running, who wants to understand Find My Data by driving it — one guided walkthrough per seeded persona, about 10 minutes each. It applies to release 26.7.15.0. Everything below runs against the deterministic Microsoft 365–shaped fixture tenant for the fictional demo org Meridian Grove Holdings — no cloud credentials, no live tenant. Where a capability is feature-gated or mock-only, the walkthrough says so; see STATUS.md for the full honest capability table.

Before you begin

Requirements: Bun ≥ 1.3 (tested with 1.3.14). No Node.js, no database server, no Docker.
Open http://localhost:5173. You land on a persona picker: this is development identity mode (FMD_AUTH_MODE=dev), explicitly banner-marked in the UI, and refused at boot when FMD_ENV=production (see ADR-0004). Entra ID is the production sign-in path; the OIDC flow itself is a documented seam, not active in this build. bun run seed leaves the tenant in a post-onboarding state: org profile and a policy document ingested, an HR + Finance taxonomy generated by the mock AI provider and human-approved, owners assigned, the mock M365 connector registered with three source scopes, and a completed baseline inventory scan of all scopes. That means every persona has something real to look at immediately. To reset at any point: rm -rf packages/server/data && bun run seed.

The seeded personas and what they can see

Navigation is role-conditional (packages/web/src/App.tsx); enforcement is capability-based on the server, deny by default (packages/shared/src/capabilities.ts). What each persona’s sidebar actually shows: Two deliberate exclusions worth noticing as you switch personas (use the Sign out button in the sidebar): the platform admin has no review or evidence capabilities — operating the machine does not grant access to what it finds — and the auditor reads everything relevant to oversight but can mutate nothing. Evidence redaction applies to auditors too.

1. Platform admin — Avery Chen

Operate the pipeline: setup state, connectivity, scans, fleet, metrics, change notifications, Teams/Exchange. Sign in as Avery Chen.

Setup & config (/setup)

The Onboarding checklist is derived entirely from observable database state — nothing is a stored “wizard step”. Eight steps, six required (two marked optional): describe the organization, upload governing policy (optional), generate a taxonomy draft, approve domains and information types, assign data-domain owners, connect a source, set governed-location expectations (optional), run the first scan. After seeding, all required steps show done and the bar reads “Required steps complete — the platform loop is live”. Each step names the capability that gates it (e.g. governance.owner.assign) and links to the page where it happens. Below the checklist:
  • Data handling — switch the tenant profile between Metadata only, Minimized evidence (recommended), and Enhanced evidence. Changing it bumps the tenant config version, which participates in the stage cache key, so evidence-bearing stages re-derive on the next scan. This is the one tenant setting writable from this page (tenant.profile.write).
  • Runtime & connector — read-only, boot-bound configuration: environment, auth mode, AI provider, connector mode. Secrets are shown only as configured/not-configured flags (tenant id, client id, client secret, remediation identity). Feature flags are listed the same way.
  • Connectivity test — click Test connector. In mock mode the probe reports the fixture reachable with its scope count. In graph mode this same probe was validated once against the live CDX tenant (app-only token + site read — see cdx-test-runbook.md); it is honest about failure rather than pretending.
  • Licensing and Fleet-health telemetry — a locally verified signed entitlement (with offline grace) and an opt-out telemetry panel that shows the exact payload that would be sent. The payload is strictly allowlisted: licensing and health bands only, no customer content. With no entitlement configured (dev), the card says so.

Operations (/operations)

The Integration modes card is the honesty dashboard: each integration is chipped live, mock, blocked, or disabled — blocked capabilities state their prerequisites in permissions-manifest.md rather than pretending to work. Source scopes lists the three fixture scopes (“FMD-CDX HR Authoritative — Screening”, “FMD-CDX Project Phoenix — Documents”, “OneDrive — Priya Raman (fixture)”) with mode, coverage state, asset count, and delta-cursor status. Per scope you get three buttons: Inventory, Delta (enabled once a cursor exists), and Watch (creates a change-notification subscription). Recent campaigns shows running scans with Pause/Resume. Now run the core operator loop:
  1. In Simulate source changes (fixture) — development-only controls that mutate the in-memory mock tenant — click one of: Add a new screening file, Edit content of Roussel report, Rename the merit letter, Overshare Walsh report (tenant-wide), Remove label from Quintana report, Delete the handbook excerpt, or Invalidate delta cursor (410 resync).
  2. Click Delta on the HR scope and watch the pipeline react incrementally in Metrics & observability: queue pending / in flight / oldest queue age / dead letters, extraction outcomes, stage latency percentiles (p50/p95/max), and counters. Permission-only changes never re-fetch content — this is test-enforced, not aspirational.
  3. Click Watch on the HR scope, then under Change notifications click Simulate a change (dev). The notification appears in Recent notifications & freshness with its outcome and reconcile lag. A notification is treated as a hint — the pipeline always re-reads the delta feed, never the notification body. Live Graph subscriptions require a public webhook URL and remain honestly blocked without one; the simulator drives the identical code path.
Note a dev-only quirk: fixture mutations live in server memory, so a server restart resets them while the database keeps its observations. A delta scan reconciles. The Scanner fleet card shows registered scanners with capabilities, heartbeat, leased/processed/failed counts; an offline scanner’s in-flight work is reclaimed for takeover (bun run worker starts one as a separate process if you want to see a second fleet member). Finally, the Microsoft Teams and Microsoft Exchange cards: click Sync Teams and Sync Exchange. Both connectors are built and mock-validated; their live Graph paths are feature-gated (FMD_FEATURE_TEAMS_CONNECTOR, FMD_FEATURE_EXCHANGE_CONNECTOR). Two identity rules are visible in the tables: a Teams channel file is canonicalized to its backing SharePoint document (never a second identity), and an Exchange attachment is a copy, so a content match to a SharePoint document is recorded as similarity, never merged. Work queue (with dead letters carrying safe diagnostics only) and Recent log events round out the page — logs are redacted by default, end to end, and a test scans for leaks.

2. Governance admin — Sam Whitfield (with Lena Fischer)

Own the taxonomy and the governed model-release loop. Sign in as Sam Whitfield.

Onboarding state

Open Setup & config — governance admins share this page — and note the checklist is complete: the seed created the org profile and ingested a policy document through the same governance services the API exposes. There is currently no UI form for the profile or policy upload; they are API endpoints (this is honest, not an omission — the UI covers review and approval):
  • GET/POST /api/onboarding/profile — org name, industries, geographies, description (grounds taxonomy generation)
  • POST /api/onboarding/policy-documents{ title, filename, text }; sections are parsed so regulatory mappings can cite them
  • GET /api/onboarding/policy-documents

Governance (/governance)

The page motto is the design rule: generated objects stay drafts until a human approves them.
  • The seeded HR/Finance taxonomy was produced by exactly this loop: the deterministic mock AI provider proposed it as draft, and the seed then performed the governance approval, so everything you see carries approved status with provenance chips. (Azure OpenAI / Anthropic adapters exist behind config, unexercised by tests — the mock is the default.)
  • Generate draft taxonomy (mock AI) re-runs generation. It is duplicate-safe: the provider skips domain names that already exist, so on a freshly seeded tenant (where HR and Finance are already approved) it honestly creates zero new drafts rather than duplicating them. Whenever drafts do exist, each draft domain shows an Approve domain button and each draft information type an Approve button (governance.taxonomy.approve), and the Home page shows governance admins a draft-taxonomy count until review is done.
  • Regulatory mapping candidates appear per domain with jurisdiction, rationale, and — where the mock provider grounded them — a citation into the uploaded policy (“cites policy §…”). The UI is explicit: mapped as relevant — not a determination of legal compliance.
  • Domain owners shows active assignments (Priya Raman → Human Resources, Diego Alvarez → Finance) with attestation state. Assigning owners is API-driven: POST /api/governance/owners (principalId, domainId, kind: owner|delegate|steward, optional attestationDays), with evidence-ranked suggestions from GET /api/governance/owner-suggestions?domainId=….
  • Release ensemble + re-score is the quick path: it creates a new ensemble release and re-scores retained features without any source I/O (test-enforced). The governed path is the next section.

Model releases (/models) — the governed learning loop

Prerequisite: dataset candidates come from owner review decisions, so run part of the domain owner walkthrough first (or after) — every confirmation (“mine” in any form) and every “not a match” decision Priya makes lands here as a candidate (domain routing and deferrals do not). Never silent training.
  1. Dataset candidates — approve or reject each pending candidate (a positive or counterexample derived from a review decision, with the model’s confidence at the time).
  2. Snapshot a dataset — name it (e.g. hr-baseline-v1), pick an eval fraction, and choose the consent scope: Tenant internal only or Vendor shareable (explicit). The split is cluster-aware: near-duplicate clusters stay on one side to prevent leakage.
  3. Propose an ensemble release — tune the candidate decision threshold, select the snapshot to evaluate against, write a rationale, and click Propose & evaluate. The release row shows candidate-vs-current precision, recall, and F1 on the held-out labels.
  4. Separation of duties — this is the point where Sam must stop. The server refuses self-approval: “Separation of duties: a release must be approved by someone other than its proposer.” Sign out and sign in as Lena Fischer, the second governance admin. On /models, the evaluated release now shows Approve / Reject.
  5. Once approved, Promote & rescore activates the new ensemble and re-scores without touching sources; a promoted release can later be rolled back (forward-applied, history preserved).
This whole loop also ran end-to-end on live CDX data in a prior validated session (real HR candidates, SoD blocking self-approval, 174 assets rescored) — see STATUS.md.

3. Domain owner — Priya Raman

The heart of the product: “Is this yours?” Sign in as Priya Raman.

Home (/home)

Her HR domain card shows confirmed assets, AI-inferred candidates, decisions waiting (with a link into Review), and what changed in the last 7 days, plus open findings, the attestation state, and source coverage for HR-governed scopes. Note the caption under coverage: a low number of findings can mean a clean environment or incomplete coverage — they are not the same thing.

My Data Landscape (/landscape)

Aggregate before detail: information-type cards (assets / confirmed / unlabeled, across N locations) that filter the asset table when clicked, and a full-text search box over titles, keyphrases, and excerpts. Every row drills into asset detail.

Review (/review) — keyboard-first

The queue shows prioritized candidates with the question “Is this yours?”. Keyboard shortcuts (verified in packages/web/src/pages/Review.tsx; never active while typing in an input): Each card explains itself: signed evidence weights with provenance chips, exposure chips (e.g. tenant-wide sharing), cluster context (“exact duplicate family · N items”), label state, a confidence bar, and — under Priya’s asset.evidence.excerpt.read capability — bounded, redacted excerpts. Excerpt access is audited. Confirm the top candidate (the README demo starts with the Walsh screening copy found in the project collaboration site) and watch the propagation acknowledgment: related byte-identical and same-template candidates are reprioritized with stated reasons. Propagation never auto-confirms — a human decided one asset, and the system only re-ranks its relatives. Your decision also just created a dataset candidate for the governance admins’ model-release loop.

Asset detail (/assets/:id)

From Review or Landscape, open any asset:
  • Classification & provenance — assertion chains with confidence, explanation, and human state; the original model inference is never destroyed by a correction.
  • Risk — named components with notes, policy version, and computation time.
  • Connections — a bounded graph plus a synchronized table where every connection has a reason.
  • Semantically similar documents — nearest neighbors by embedding cosine (approximate vector search, deterministic feature-hash embeddings by default), filtered to what Priya is allowed to see.
  • Access & label — permission grants with an explicit completeness caveat: absence of a grant here is not evidence it does not exist.
  • History — location and version timelines; Redacted evidence excerpts where held; findings with a Draft an action → link.

Analyst (/analyst)

Ask the canonical question (also available as an example button):
Show employee background content on SharePoint sites that do not appear to be owned by HR.
The question becomes a typed, server-validated plan — never free-form database access — and the tenant/domain scope is injected server-side so a plan cannot widen it (see ADR-0009). The answer arrives with its interpretation (marked as AI output to verify against the rows), scope note, evidence rows linking to assets, and a coverage & freshness section including blind spots.

Draft a label action (/actions)

In Draft an action: paste an asset ID from asset detail or findings (ast_…), choose Apply Purview sensitivity label, pick a label from the catalog, and write a business/policy justification (minimum 10 characters — the button stays disabled without it). Preview & draft, then Submit. The status moves to awaiting approval — and stops there: Priya can draft and submit, but approval requires Morgan. Requesters can never approve their own actions. Isolation check: sign in as Diego Alvarez. Same navigation, same pages — zero HR data. His landscape, queue, and Analyst answers are Finance-scoped, and probing an HR asset URL returns 404 with no existence leak (test-enforced).

4. Remediation approver — Morgan Ellis

Approve or reject governed changes. Two minutes of clicking, and every click is audited. Sign in as Morgan Ellis. Home shows an Approvals card counting actions awaiting approval, linking to /actions. The Action ledger shows each request with its target, kind, current → desired state, requester, justification, status, and verification result. On a row in awaiting_approval, Morgan sees Approve and Reject. Approve Priya’s label action and watch the state machine finish: execute once (idempotent — duplicate delivery produces one mutation, test-enforced), then verify against the source, then the related label-gap finding resolves on recompute. If the target changed since preview, the action lands in drifted and must be re-previewed — no stale writes. The full state machine is ADR-0010. Honesty note: in this demo the label write executes against the mock fixture. The live Purview label write path is implemented but feature-gated (FMD_FEATURE_PURVIEW_LABEL_WRITE plus a separate remediation identity, FMD_GRAPH_REMEDIATION_*); it refuses to run when unconfigured rather than pretending. Morgan holds action.approve/action.cancel tenant-wide plus asset metadata read — he approves, but he does not draft actions or browse evidence excerpts.

5. Auditor — Ren Nakamura

Read everything that matters for oversight; change nothing. Sign in as Ren Nakamura. Audit trail (/audit) is the page only this role sees: an append-only, hash-chained business audit with a category filter — auth, config, governance, scan, evidence_access, review, analyst, action, model. After the walkthroughs above, the categories tell the whole story: Priya’s review decisions and excerpt accesses, Sam’s proposal and Lena’s approval, Morgan’s approval and the execution/verification, Avery’s scans and config changes. Details are redaction-safe JSON — evidence redaction applies to auditors too, and the chain is verifiable. Ren also gets read access across Governance (taxonomy, owners, provenance), Operations (scopes, campaigns, fleet, metrics, notifications, work queue), Findings, and the Actions ledger. The pages render their controls, but every mutation — starting a scan, syncing Teams, approving anything — is refused by the server: Ren’s capabilities (audit.read, operations.read, read-only governance/findings/scan) contain no writes, and authorization is deny-by-default.

Where to next

  • STATUS.md — the honest capability table: built + validated live (CDX), built + mock-validated + live-gated, and not built
  • architecture.md — how the modules you just used fit together
  • permissions-manifest.md — exact Microsoft Graph permissions each live capability needs
  • cdx-test-runbook.md — the live-tenant validation record and plan
  • threat-model.md — why the capability exclusions above look the way they do