Before beginning setup, ensure you have:
- Azure Subscription with Owner or Contributor permissions
- Microsoft 365 Tenant with SharePoint Online
- Azure subscription access (for Logic App deployment)
- Azure AD admin access for app registration
- Anthropic API Key (Claude AI) — optional, AI validation currently disabled
- Development tools:
- Python 3.11+
- Azure Functions Core Tools v4
- Git
- VS Code (recommended)
This app will authenticate the Azure Function to access SharePoint.
-
Navigate to Azure Portal
- Go to: https://portal.azure.com
- Sign in with admin credentials
-
Create App Registration
- Search for "Azure Active Directory" or "Microsoft Entra ID"
- Click App registrations → New registration
Settings:
- Name:
MaceStyleValidator-App - Supported account types: Single tenant
- Redirect URI: Leave blank
- Click Register
-
Note the Application Details
Tenant ID: [Copy from Overview page] Client ID (Application ID): [Copy from Overview page]Save these values - you'll need them later!
-
Create Client Secret
- Click Certificates & secrets → New client secret
- Description:
MaceStyleValidator-Secret - Expires: 24 months (or as per your policy)
- Click Add
- Copy the secret value immediately (won't be shown again)
Client Secret: [Copy the Value, not the Secret ID] -
Configure API Permissions
- Click API permissions → Add a permission
- Select Microsoft Graph → Application permissions
Add this permission:
-
Sites.Selected— Grants access to no sites by default; access is granted per-site via the Graph API -
Click Add permissions
-
Click Grant admin consent for [Tenant Name]
-
Confirm by clicking Yes
✅ Verify: Permission shows "Granted for [Tenant]"
Note:
Sites.Selectedalone does not grant access to any SharePoint site. After completing the App Registration, you must grant per-site access — see docs/azure-admin-setup.md for instructions.
-
Create Function App Resource
- In Azure Portal, click Create a resource
- Search for "Function App"
- Click Create
Basic Settings:
Resource Group: Create new → "rg-macestyle" Function App name: "func-mace-validator-prod" Publish: Code Runtime stack: Python Version: 3.11 Region: [Choose closest to your SharePoint tenant] Operating System: Linux Plan type: Consumption (Serverless)- Click Review + create → Create
- Wait for deployment (2-3 minutes)
-
Configure Application Settings
- Go to Function App → Configuration → Application settings
- Click + New application setting for each:
Name: SHAREPOINT_TENANT_ID Value: [Your Tenant ID from step 1.1] Name: SHAREPOINT_CLIENT_ID Value: [Your Client ID from step 1.1] Name: SHAREPOINT_CLIENT_SECRET Value: [Your Client Secret from step 1.1] Name: SHAREPOINT_SITE_URL Value: https://[yourtenant].sharepoint.com/sites/StyleValidation Name: ANTHROPIC_API_KEY Value: [Your Claude API key - get from console.anthropic.com] (optional — AI currently disabled)- Click Save → Continue
-
Configure CORS (if calling from web app)
- Go to CORS under API section
- Add allowed origins if needed
- Click Save
Note: Claude AI validation is currently disabled via the
ENABLE_CLAUDE_AIflag. This step is only needed if you plan to re-enable AI validation.
-
Sign up for Anthropic
- Go to: https://console.anthropic.com
- Create account or sign in
-
Create API Key
- Navigate to API Keys
- Click Create Key
- Name:
MaceStyleValidator - Click Create
- Copy the key (starts with
sk-ant-...)
-
Fund your account
- Add billing information
- Add credits (recommended: $10 minimum)
- Claude Haiku 4.5 costs ~$0.01 per document (Word only)
-
Create Site Collection (if not exists)
- Go to SharePoint Admin Center
- Sites → Active sites → Create
- Type: Team site
- Site name:
Style Validation - Site address:
/sites/StyleValidation - Primary administrator: [Your account]
- Click Finish
-
Verify Site URL
Expected: https://[tenant].sharepoint.com/sites/StyleValidation
-
Navigate to site
- Go to:
https://[tenant].sharepoint.com/sites/StyleValidation
- Go to:
-
Create List
- Click New → List
- Name:
Style Rules - Description:
Validation rules for style checking - Click Create
-
Add Columns
Column 1: RuleType
- Type: Choice
- Choices:
Font Language Grammar Punctuation Capitalisation Layout - Default: (none)
Column 2: DocumentType
- Type: Choice
- Choices:
Word Visio Excel PowerPoint Both All - Default: Word
Column 3: CheckValue
- Type: Single line of text
Column 4: ExpectedValue
- Type: Single line of text
Column 5: AutoFix
- Type: Yes/No
- Default: Yes
Column 6: UseAI
- Type: Yes/No
- Default: No
Column 7: Priority
- Type: Number
- Min: 1
- Max: 999
- Default: 100
-
Populate Rules
- Option A: Use the
populate_style_rules.pyscript - Option B: Manually add rules from the style guide
To use the script:
cd MaceStyleValidator # Set environment variables export SHAREPOINT_TENANT_ID="[your-tenant-id]" export SHAREPOINT_CLIENT_ID="[your-client-id]" export SHAREPOINT_CLIENT_SECRET="[your-client-secret]" export SHAREPOINT_SITE_URL="https://[tenant].sharepoint.com/sites/StyleValidation" # Run script python3 populate_style_rules.py
This will add ~70 style rules automatically.
- Option A: Use the
-
Create List
- Name:
Validation Results - Description:
History of document validations - Click Create
- Name:
-
Add Columns
Column 1: FileName
- Type: Single line of text
Column 2: ValidationDate
- Type: Date and Time
- Format: Date & Time
Column 3: Status
- Type: Choice
- Choices:
Passed Review Required Failed - Default: (none)
Column 4: IssuesFound
- Type: Single line of text
- (Stored as text for simplicity)
Column 5: IssuesFixed
- Type: Single line of text
Column 6: ReportLink
- Type: Hyperlink or Picture
-
Get List ID (needed for code)
- Go to List Settings → copy URL
- Extract ID from URL:
List={GUID} - Or run:
python3 inspect_validation_results.py
Note: List IDs are configurable via environment variables:
SHAREPOINT_VALIDATION_RESULTS_ID— GUID of the Validation Results listSHAREPOINT_DOC_LIBRARY_ID— GUID of the Document Library
Set these in Azure Function App Settings for production.
-
Use Default or Create New
- Option A: Use existing "Documents" library
- Option B: Create new library named "Validated Documents"
-
Add Custom Columns
Column 1: ValidationStatus
- Type: Choice
- Choices:
Not Validated Validate Now Validating... Passed Review Required Failed - Default: Not Validated
- Colour coding (optional):
- Validating... = Yellow
- Passed = Green
- Review Required = Amber
- Failed = Red
Column 2: ValidationResultLink
- Type: Hyperlink or Picture
Column 3: LastValidated
- Type: Date and Time
- Format: Date & Time
-
Enable Versioning (Important!)
- Library Settings → Versioning settings
- Document Version History: Yes
- Create major versions: Yes
- Keep versions: At least 50 (or more)
- Click OK
-
Set Permissions (if needed)
- Ensure users have:
- Read: To view documents
- Edit: To upload and modify
- Contribute: To trigger validation
- Ensure users have:
# Clone the repository
git clone https://github.com/stephencummins/MaceStyle.git
cd MaceStyle/MaceStyleValidator-
Create virtual environment
python3 -m venv .venv source .venv/bin/activate # On Windows: .venv\Scripts\activate
-
Install dependencies
pip install -r requirements.txt
-
Create local.settings.json
cat > local.settings.json << 'EOF' { "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "python", "SHAREPOINT_TENANT_ID": "[your-tenant-id]", "SHAREPOINT_CLIENT_ID": "[your-client-id]", "SHAREPOINT_CLIENT_SECRET": "[your-client-secret]", "SHAREPOINT_SITE_URL": "https://[tenant].sharepoint.com/sites/StyleValidation", "ANTHROPIC_API_KEY": "[your-anthropic-api-key]" } } EOF
Replace all
[...]placeholders with your actual values -
Test locally
func start
You should see:
Functions: ListDocuments: [GET,POST] http://localhost:7071/api/listdocuments TestSharePoint: [GET,POST] http://localhost:7071/api/testsharepoint ValidateDocument: [POST] http://localhost:7071/api/validatedocument
-
Login to Azure
az login
-
Set subscription (if you have multiple)
az account set --subscription "[Your Subscription Name or ID]"
-
Deploy Function
func azure functionapp publish func-mace-validator-prod
Wait for deployment to complete (2-3 minutes).
-
Verify deployment
- Go to Azure Portal → Function App
- Check Functions tab - should show 3 functions
- Check App Keys → copy Host key (default)
-
Get Function URL
https://func-mace-validator-prod.azurewebsites.net/api/validatedocumentSave this URL - needed for Power Automate!
An ARM template is provided at infra/logic-app.json that deploys a Consumption Logic App. This is preferred over Power Automate for production as it lives in the Azure subscription and can be deployed via ARM/DevOps.
az deployment group create \
--resource-group rg-macestyle \
--template-file infra/logic-app.json \
--parameters infra/logic-app.parameters.json \
--parameters functionAppKey="<function-host-key>" \
--parameters sharepointDocLibraryId="<library-guid>"After deployment:
- Go to Azure Portal → Resource Group → API Connections →
sharepointonline - Click Edit API connection
- Click Authorize and sign in with a SharePoint account
- Click Save
The Logic App:
- Triggers on file create/modify in the SharePoint Document Library
- Filters to supported file types (.docx, .xlsx, .pptx, .vsdx, etc.)
- Sets ValidationStatus to "Validating..."
- Gets file content and base64-encodes it
- Calls the Function App (
POST /api/ValidateDocument) with 10-minute timeout - Parses the JSON response
- If fixes were applied, uploads the corrected file back
- Updates ValidationStatus, Description, ValidationReport, ValidationResultLink, and LastValidated
An azure-pipelines.yml is provided in the repo root for automated deployment:
- Build + test on push to
main - Deploy to dev (automatic)
- Deploy to prod (with approval gate)
- Deploy Logic App ARM template
See docs/prod-deployment-guide.md for DevOps setup instructions.
- Upload a test document to the SharePoint library
- Check Logic App run history in Azure Portal
- Verify document status updated, report generated, and results saved
Create test_validation.docx with:
Content to test:
1. American spelling: finalized, color, center, analyze
2. Contractions: can't, don't, won't
3. Symbols: M&S, 50%
4. Wrong font: (Set some text to Calibri or Times New Roman)
5. Numbers: 1000, 2000, 3000
-
Upload to SharePoint
- Upload
test_validation.docx - Wait for "Validating..." status
- Upload
-
Check Results (should complete in 10-20 seconds)
- Status: Should be "Passed"
- ValidationResultLink: Should have link
-
Open HTML Report
- Click ValidationResultLink
- Should show:
- Fixes Applied: Multiple corrections
- Issues: All issues listed
-
Download Fixed Document
- Download the document
- Open in Word
- Verify:
- ✅ finalized → finalised
- ✅ color → colour
- ✅ can't → cannot
- ✅ M&S → M and S
- ✅ 50% → 50 percent
- ✅ All text is Arial
- ✅ Numbers: 1,000, 2,000, 3,000
Test 1: Invalid file type
- Upload
test.txt - Expected: Error or status "Failed"
Test 2: Large file
- Upload 100+ page document
- Expected: Completes (may take 30+ seconds)
Test 3: Corrupted file
- Upload corrupted .docx
- Expected: Status "Failed" with error
Application Insights:
Azure Portal → Function App → Application Insights
Key Metrics:
- Request rate
- Average duration
- Failure rate
- Dependency calls (Graph API, Claude API)
Live Metrics:
Application Insights → Live Metrics
Monitor:
- Real-time requests
- Failures as they happen
- Performance issues
Log Stream:
Function App → Log stream
View:
- Real-time execution logs
- Debugging information
- Error details
Azure Costs:
Azure Portal → Cost Management + Billing → Cost Analysis
Filter by:
- Resource Group: rg-macestyle
- Service: Azure Functions, Application Insights
Anthropic API Costs:
console.anthropic.com → Usage
Track:
- Total API calls
- Tokens used
- Cost per month
Expected Monthly Costs:
Azure Functions: $0-10 (Consumption plan)
Application Insights: $0-5 (Basic tier)
Claude API: ~$0.01 per document
SharePoint: Included in M365
Example:
- 1,000 documents/month = ~$10-20 total
- 100 documents/month = ~$1-5 total
Optimize validation speed:
-
Reduce AI rules (if too slow)
- Disable UseAI for simple rules
- Keep AI for complex language checks
-
Batch operations (for large documents)
- Split very large files
- Process in chunks
-
Cache Graph API tokens
- Already implemented (60-minute cache)
-
Use faster Claude model (if needed)
- Current: Haiku (fast, cheap)
- Alternative: Sonnet (slower, more accurate)
Weekly:
- Check error logs for patterns
- Review failed validations
- Verify costs are within budget
Monthly:
- Review and update style rules
- Analyze validation metrics
- Check for API updates (Graph, Anthropic)
Quarterly:
- Review permissions and security
- Update dependencies
- Rotate secrets if required
Do: ✅ Store secrets in Azure Key Vault ✅ Use managed identities when possible ✅ Rotate secrets every 12 months ✅ Use different secrets for dev/prod
Don't: ❌ Commit secrets to Git ❌ Share secrets via email/chat ❌ Use same secrets across environments ❌ Store secrets in code
Principle of Least Privilege:
-
Azure Function
- Uses
Sites.Selectedwith per-sitewritegrant (not tenant-wide access) - No user impersonation
- Uses
-
SharePoint Users
- Read: View documents and reports
- Edit: Upload and modify documents
- No Contribute to Style Rules list
-
Administrators
- Manage Style Rules
- View logs
- Modify configuration
Data Privacy:
- Documents processed in-memory only
- No persistent storage of content
- Audit trail in Validation Results
GDPR Considerations:
- Personal data in documents (if any)
- Retention policy for Validation Results
- Right to deletion (version history cleanup)
Cause: App registration permissions not granted
Solution:
- Azure Portal → App Registration
- API Permissions → Grant admin consent
- Verify green checkmarks
Cause: Logic App disabled or broken
Solution:
- Azure Portal → Logic App → Check run history
- Review last run error
- Check SharePoint API connection authorisation
Cause: List ID mismatch
Solution:
- Run
inspect_validation_results.py - Get actual list ID
- Update in
sharepoint_results.pyline 35
Note: Claude AI is currently disabled. This section only applies if
ENABLE_CLAUDE_AI = True.
Cause: Invalid API key or insufficient credits
Solution:
- Verify API key in Function App settings
- Check Anthropic console for credits
- Add credits if balance is low
Cause: Missing fileUrl parameter
Solution:
- Check Logic App request body includes fileUrl
- Review Logic App run history for the specific run
SharePoint Lists:
- Export Style Rules to Excel monthly
- Export Validation Results quarterly
- Use SharePoint Online backup (included in M365)
Azure Function Code:
- Git repository (primary backup)
- Azure DevOps / GitHub (secondary)
- Local developer machines
Secrets:
- Document in secure password manager
- Store offline backup in safe
- Keep recovery contacts updated
Scenario: SharePoint site deleted
- Restore from SharePoint Recycle Bin (93 days)
- Or restore from M365 admin center backup
- Re-run populate_style_rules.py to restore rules
Scenario: Azure Function deleted
- Redeploy from Git
- Reconfigure App Settings
- Test with sample document
Scenario: App registration deleted
- Create new app registration
- Update secrets in Function App
- Re-grant API permissions
# Azure Function App Settings
SHAREPOINT_TENANT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
SHAREPOINT_CLIENT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
SHAREPOINT_CLIENT_SECRET="your-client-secret-value"
SHAREPOINT_SITE_URL="https://tenant.sharepoint.com/sites/StyleValidation"
ANTHROPIC_API_KEY="sk-ant-xxxxxxxxxxxxxxxxxxxxx"Connect-PnPOnline -Url "https://tenant.sharepoint.com/sites/StyleValidation" -Interactive
Get-PnPSite | Select IdConnect-PnPOnline -Url "https://tenant.sharepoint.com/sites/StyleValidation" -Interactive
Get-PnPList | Select Title, IdConnect-PnPOnline -Url "https://tenant.sharepoint.com/sites/StyleValidation" -Interactive
Get-PnPListItem -List "Style Rules" | Export-Csv "StyleRules_Backup.csv"Before going live, verify:
- App registration created with correct permissions
- Azure Function deployed and responding
- SharePoint lists created with all columns
- Style Rules populated
- Document library configured with custom columns
- Logic App deployed and SharePoint connection authorised
- Test document validates successfully
- HTML report generates and uploads
- Validation Results list populates
- Document metadata updates with result link
- All secrets stored securely
- Monitoring and logging configured
- User guide distributed to team
- Admin contacts documented
- Azure Functions GitHub: https://github.com/Azure/azure-functions-python-worker
- Power Automate Community: https://powerusers.microsoft.com/
- Last Updated: March 2026
- Version: 5.0
- Author: [Your Name/Team]
- License: [Your License]