Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 10 additions & 142 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1,145 +1,13 @@
# Copilot instructions for SMBBestPracticeTool
---
authority: pointer
applies-to: "**"
last-reviewed: 2026-09-23
---

PowerShell automation that configures Microsoft 365 tenants against Microsoft's
recommended best-practice baselines. `Products/<Product>/` is the layout for
each product; today the only shipped product is **Purview**
(`Products/Purview/`). Everything below is Purview-specific unless noted.
# Copilot instructions

## Validating changes (there is no Pester/unit-test suite)
Read [AGENTS.md](../AGENTS.md) first. It is the master entry point for all
repository guidance, including verification, conventions, and required PR and
work-item telemetry. Follow its linked documents.

This repo has no automated test framework. Validation is two-layered:

1. **Syntax/parse-check a single file** (fast, no tenant needed) — the
equivalent of "run one test":
```powershell
$errs = $null; $toks = $null
[System.Management.Automation.Language.Parser]::ParseFile('Products\Purview\Modules\Setup-DLP.ps1', [ref]$toks, [ref]$errs)
if ($errs) { $errs | ForEach-Object { $_.Message } } else { 'OK' }
```
2. **`-WhatIf` dry run against a real (pilot) tenant** — every module wires
`SupportsShouldProcess`, so a full `-WhatIf` pass previews every
state-changing call without applying it:
```powershell
cd Products/Purview
.\Deploy-PurviewBestPractice.ps1 -TenantAdminUpn admin@contoso.onmicrosoft.com -WhatIf
```
Each `Setup-*.ps1` module under `Modules/` is self-contained and can also be
invoked standalone (it takes `-Config <hashtable>` from
`Config/PurviewConfig.psd1` plus its own switches) to iterate on one task
without running the whole orchestrator.

There is no lint config (no PSScriptAnalyzer settings file) and no CI beyond
GitHub Pages' automatic build/deploy for the docs site.

**Docs site local preview** (Jekyll, only needed when editing `*.md` under
`Products/Purview/docs/` or site config):
```powershell
bundle install # one-time, needs Ruby
bundle exec jekyll serve # http://127.0.0.1:4000/BestPractice_Deploy-Scripts/
```

## Architecture: how a deployment run flows

`Deploy-PurviewBestPractice.ps1` is the orchestrator. It does NOT dot-source
its modules — each task is invoked as a **separate script process**
(`& $script @taskArgs`), so every `Modules/Setup-*.ps1` is independently
runnable and testable on its own:

1. `Connect-PurviewServices.ps1` — connects Graph (first, to avoid an MSAL DLL
version race with EXO), Exchange Online, Security & Compliance (IPPS), and
SharePoint Online. Returns/consumes a tenant-identity object used to resolve
the `{TenantDomain}` encryption-scope token.
2. `Setup-TenantSettings.ps1` — audit log, SPO/AIP integration, PDF labels,
container labels, label co-authoring.
3. `Setup-SensitivityLabels.ps1` — creates/adopts labels from
`Config/PurviewConfig.psd1`, sets priority order, publishes the policy.
4. `Setup-DLP.ps1` — DLP policies/rules that reference labels **by resolved
GUID**, never by display name.
5. `Setup-Retention.ps1` — opt-in only (`-ApplyRetention`; destructive default).
6. `Setup-AIGovernance.ps1` — Copilot DLP policies (E5/Purview Suite only).

Shared building blocks every module dot-sources:
- `Invoke-WithTransientRetry.ps1` — the ONLY retry mechanism; wraps IPPS/EXO/
SPO/Graph calls with backoff+jitter and auto-emits run-log entries. Never
hand-roll a retry loop.
- `PurviewRunLog.ps1` — `Add-RunLogEntry`, the structured logger every
observable action must call (see below).
- `Write-PurviewHtmlReport.ps1` — renders the run log into the end-of-run
HTML + JSON report (secrets stripped).

All tunables (label names/taxonomy, DLP policies, retention duration,
encryption rights) live in **`Config/PurviewConfig.psd1`** — never hardcode a
label name, policy name, or duration in a module; add/edit a config key
instead.

## Key conventions

- **Idempotency is read-modify-write, always.** `Get-*` current state first;
if present and matching intent, no-op; if present and different, merge the
change into the existing object (never overwrite other fields customers may
have set by hand or with another tool). Every object the toolkit creates is
stamped with `ManagedByTag` (`Config/PurviewConfig.psd1`,
`'[Managed by SMBTool Purview Toolkit]'`) so re-runs can recognize their own
objects; an unstamped existing object with the same name aborts the run
unless `-AdoptExisting` is passed.
- **Labels are matched/adopted by a stable internal signature, not
DisplayName.** Built-in Microsoft labels carry a `BuiltInName` field in
config (`defa4170-0d19-0005-NNNN-bc88714345d2`) — this is what makes
adoption work across locales and both classic/modern label schemes.
Never match a label by its (localized, mutable) `DisplayName`.
- **DLP/AI rules bind labels by resolved GUID, never by name.** A persisted
rule's label operand legitimately shows `name == id == <GUID>` — that's
correct, not a bug.
- **Run-log discipline (`Add-RunLogEntry`)**: every observable action —
including a step that was *skipped* — must emit an entry, not just a
`Write-Host` line. `-Status` is a hard `ValidateSet`:
`Started, Succeeded, Created, Updated, Adopted, Skipped, Failed, Retried, Info`
— **`Warning` is NOT valid** and throws a binding error. Use `Info` (detail
prefixed `WARNING:`) or `Skipped` instead.
- **License gating**: `-BPOnly` blocks any E5/Purview-Suite-only feature;
`-NoLicenseAutoDetect` disables the `/subscribedSkus` auto-detect;
per-feature `-Skip<X>` switches are the operator's opt-out. A `-Skip*`
switch is an escape hatch, not a fix — if a feature is failing, fix the
root cause rather than reaching for the skip switch.
- **Irreversible/one-way tenant operations must be opt-in switches**, never
default-on, with the irreversibility called out in `.PARAMETER` help and
linked to the Microsoft Learn page describing it (e.g.
`-ApplyRetention`, `-EnableLabelCoAuthoring`).
- **Documentation parity**: a code change that alters operator-facing
behaviour (defaults, licensing, opt-in switches, output) must update every
doc describing that behaviour in the same commit —
`Products/Purview/README.md`, `Products/Purview/docs/*.md`, and the
matching `.html` companions (`End-User-Adoption-Guide.html`,
`What-This-Tool-Does.html`, `Change-Management-Playbook.html` are richly
styled standalone artifacts embedded via `<iframe>`, not generated from the
`.md` — edit both).
- **Docs must be audience-neutral** — the toolkit is run by partners/MSPs
*and* in-house IT teams; don't address the reader as "the partner". Prefer
"the deployment team" / "whoever runs the toolkit" / "you".
- **Versioning (`CHANGELOG.md`, Keep a Changelog + SemVer)**: MAJOR = a new
*product* added to the toolkit (e.g. a future Defender product); MINOR = a
new feature or a redesign within an existing product; PATCH = a bug fix
with no behaviour change. A changed default does not by itself force MAJOR.
- **Commit messages**: imperative-mood subject ≤72 chars; body explains *why*.
Append `Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>`
on AI-assisted commits.

## Git workflow

- `main` is protected — PRs required (even for admins), no direct pushes.
- `staging` is the integration branch; work lands there first.
- Promote `staging` → `main` via PR, squash-merged; then back-merge the
resulting `main` commit into `staging` (`git merge origin/main`) so history
stays clean for the next cycle — this is the established pattern (see
`git log --oneline` for prior "Back-merge origin/main into staging" commits).
- Tag releases `vX.Y.Z` on `main` after merge; a GitHub Release can be cut from
the same tag using the CHANGELOG entry as its notes.

## Optional local context

If a gitignored `Skills/` directory is present in your checkout, it contains
much more detailed per-module decision logs and conventions
(`Skills/_CONVENTIONS.md`, `Skills/Purview/_CONVENTIONS.md`,
`Skills/Purview/<Module>.skill.md`) built up over the project's history. It is
not part of the git repository (not visible on a fresh clone), so treat it as
a bonus when present, not a dependency.
Do not duplicate that guidance here; update the topic's authoritative document.
67 changes: 38 additions & 29 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,40 @@
---
authority: canonical
applies-to: "**"
last-reviewed: 2026-09-23
---

# AGENTS.md — BestPractice_Deploy-Scripts

**PowerShell deployment scripts** implementing Microsoft best-practice configurations
(currently Microsoft Purview) as repeatable, idempotent automation. This file is the entry
point for humans and coding agents. Copilot-specific guidance already lives in
[`.github/copilot-instructions.md`](.github/copilot-instructions.md).

## Repository map
| Path | What lives here |
| --- | --- |
| `Products/Purview/Deploy-PurviewBestPractice.ps1` | Top-level orchestrator. |
| `Products/Purview/Modules/` | Task modules: `Setup-DLP.ps1`, `Setup-Retention.ps1`, `Setup-SensitivityLabels.ps1`, `Setup-AIGovernance.ps1`, `Setup-TenantSettings.ps1`, `Connect-PurviewServices.ps1`, `Invoke-WithTransientRetry.ps1`, `PurviewRunLog.ps1`, `Write-PurviewHtmlReport.ps1`. |
| `Products/Purview/Config/PurviewConfig.psd1` | Deployment configuration (data file). |
| `Products/Purview/AdHoc/` | Standalone helper scripts. |
| `Products/Purview/docs/`, `Products/Purview/Examples/` | Playbooks, references, examples. |
| `.github/copilot-instructions.md` | Copilot guardrails. |

## Conventions
See [`docs/conventions.md`](docs/conventions.md).

## Verification / Definition of Done
```powershell
pwsh scripts/verify.ps1
```
`verify.ps1` syntax-checks every `*.ps1` under `Products/` and validates that the
`*.psd1` configuration files parse as PowerShell data files. A change is done when
`verify.ps1` passes and the affected deployment path has been dry-run/validated against a
non-production tenant.

## PR & work-item telemetry — required
Every PR must follow [`.github/instructions/telemetry.instructions.md`](.github/instructions/telemetry.instructions.md).
This is the master entry point for humans and coding agents working on
SMBBestPracticeTool: repeatable, idempotent PowerShell automation for Microsoft
365 best-practice configurations. Microsoft Purview is the currently shipped
product. Read the linked guidance before editing; each topic has one owner below.

## Context and verification

- [Repository layout](docs/conventions.md#repository-layout).
- [Deployment architecture and shared helpers](docs/conventions.md#architecture-how-a-deployment-run-flows).
- [Authoring and safety conventions](docs/conventions.md#key-conventions).
- [Verification commands and definition of done](docs/conventions.md#validation-and-definition-of-done):
repository-wide checks, individual checks, pilot-tenant validation, and docs preview.
- [Branch, release, and PR workflow](docs/conventions.md#git-workflow).
- [Optional local decision logs](docs/conventions.md#optional-local-context).

## PR and work-item telemetry

Read and apply the canonical
[telemetry instructions](.github/instructions/telemetry.instructions.md)
whenever creating or updating a PR or work item.

## Authority map

| File / path | Authority | Scope |
| --- | --- | --- |
| `AGENTS.md` | Canonical entry point | Context discovery and topic ownership. |
| `docs/conventions.md` | Canonical guidance | Layout, architecture, validation, safety, authoring, and Git workflow. |
| `.github/instructions/telemetry.instructions.md` | Canonical telemetry | PR and work-item labels, tags, and description footers. |
| `.github/copilot-instructions.md` | Pointer | Redirects Copilot to this entry point. |
| `scripts/verify.ps1` | Executable verification | Local syntax and configuration checks. |
| `Products/` | Implementation and product docs | Product behavior and operator instructions. |
| [Responsible AI review](docs/Responsible-AI-Review.md) | Change review | Scope and safeguards of this context-consolidation change. |
80 changes: 80 additions & 0 deletions docs/Responsible-AI-Review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
authority: change-review
applies-to: "Tier 1 context consolidation"
last-reviewed: 2026-09-23
---

# Responsible AI Review: Tier 1 Context Consolidation

## Intended Use

Help maintainers and coding agents discover existing repository instructions
consistently. The change consolidates duplicated guidance behind `AGENTS.md`;
it does not introduce a model, agent service, deployment feature, or new tool.
Success means one authoritative location per guidance topic and reachable
verification commands from both the root entry point and Copilot's pointer.

## System and Data

Inputs are tracked repository documentation. Outputs are reorganized Markdown
guidance. No customer, tenant, or personal data is required. No new data store,
retention policy, external endpoint, or runtime permission is introduced.
Telemetry submission remains a separate, explicitly requested workflow.

## Human Control

A maintainer reviews the diff and approves the PR before merge. Existing
tenant-operation opt-ins, pilot validation, and protected-branch rules remain.
Agents must not infer permission to connect to tenants from a verification
example. Work can be stopped before merge; a follow-up PR can revert these
documentation changes without altering tenant state.

## Principle Review

### Fairness and Inclusiveness

Guidance remains audience-neutral for partners, MSPs, and in-house teams.
The shared entry point serves different agent clients without requiring
GitHub Copilot-specific knowledge.

### Reliability and Safety

Preserve deployment safeguards, verification commands, and the telemetry
instructions. Check same-repository links and topic ownership to prevent
broken discovery and contradictory copies. Keep the distinction between
static verification and actual pilot-tenant evidence explicit.

### Privacy and Security

No new permissions or automatic tenant actions are authorized. Secret and
customer-data restrictions remain in the canonical conventions. External
content cannot override repository instructions or grant permissions.

### Transparency

The authority map identifies the source for each topic. Report static checks
separately from tenant validation, and do not describe local readiness evidence
as published telemetry.

### Accountability

Repository maintainers retain review and merge accountability. When guidance
is wrong or stale, correct its authoritative document through the same PR
workflow rather than adding a competing copy.

## Evaluation

Before merge, inspect the moved guidance against the prior version, resolve
all local Markdown links and section anchors, confirm that Copilot's file is
only a pointer, and confirm that telemetry instructions are unchanged.
Run the existing static verification and maintainer quality gate. Record
actual results in the PR; this document is not evidence of checks being run.
No model benchmark or tenant deployment is applicable to this documentation-only
change. Runtime prompt-injection resistance is not evaluated or claimed.

## Decision

Ready for human review once the listed checks pass. This is not approval to
merge, deploy, or publish telemetry. Residual risk is that an agent ignores
the links; maintainers should review instruction-following failures and correct
the entry point without duplicating the detailed guidance.
Loading
Loading