From fd8b77fe6b64fef470e23ce29a91d55887f7f594 Mon Sep 17 00:00:00 2001 From: Dave Date: Thu, 20 Aug 2026 16:18:47 -0400 Subject: [PATCH] first commit --- Persona-Engine-Developer-Handoff.txt | 3873 ++++++++++++++++++++++++++ 1 file changed, 3873 insertions(+) create mode 100644 Persona-Engine-Developer-Handoff.txt diff --git a/Persona-Engine-Developer-Handoff.txt b/Persona-Engine-Developer-Handoff.txt new file mode 100644 index 0000000..2b05c68 --- /dev/null +++ b/Persona-Engine-Developer-Handoff.txt @@ -0,0 +1,3873 @@ +PERSONA ENGINE + +Phase 0 Requirements, Specification, Architecture, Plan, Decisions, and Acceptance Criteria + + + +Document status: Approved Phase 0 baseline + +Classification: Generic / Sanitized + +Intended audience: PowerShell developer, identity architect, security reviewer, DevOps engineer, tester + + + +====================================================================== + +1. DOCUMENT PURPOSE + +====================================================================== + + + +This document consolidates the requirements and decisions needed to begin execution of the Persona Engine project. It is intentionally sanitized and contains no organization name, production domain name, tenant identifier, real user information, real group identifiers, or other proprietary values. + + + +All tenant-specific values must be supplied through protected configuration, deployment variables, or approved secret/configuration stores. Examples in this document use placeholders only. + + + +The project will use GitHub Spec Kit principles and artifacts to move through: + + + + Specify -> Plan -> Tasks -> Implement + + + +The developer should treat this file as the starting baseline for the project specification. Any unresolved item must be captured as an explicit assumption, risk, or architecture decision. It must not be silently implemented. + + + +====================================================================== + +2. EXECUTIVE SUMMARY + +====================================================================== + + + +The Persona Engine is a PowerShell 7 solution for Microsoft Entra ID that: + + + +1. Enumerates Entra user accounts. + +2. Retrieves the approved user properties and related identity data required by enabled business rules. + +3. Evaluates each user against an ordered, configuration-driven rule set. + +4. Deterministically assigns exactly one persona to each successfully evaluated account. + +5. Stops processing rules for a user after the first rule matches. + +6. Assigns Unclassified when evaluation succeeds but no rule matches. + +7. Preserves the current persona when evaluation cannot be completed reliably. + +8. Compares the calculated persona with the existing persona attribute. + +9. Updates only the configured persona attribute, and only when the value has changed. + +10. Supports native PowerShell -WhatIf behavior that prevents all Microsoft Graph writes. + +11. Displays a result immediately after each user is processed. + +12. Displays configurable periodic and final summary tables. + +13. Produces structured, audit-friendly logs containing both UPN and Account Object ID. + +14. Includes a second PowerShell script for JSON configuration validation and interactive editing. + +15. Runs locally for development and testing and later as an Azure Automation PowerShell 7 Runbook. + +16. Is hosted, versioned, reviewed, tested, and deployed through Azure DevOps. + + + +Conditional Access is the first consumer of the persona value, but the output is intended to become a reusable enterprise identity-classification signal for other authorized consumers. + + + +====================================================================== + +3. PROJECT OBJECTIVES + +====================================================================== + + + +Primary objectives: + + + +- Establish one deterministic persona value for every successfully evaluated Entra user. + +- Replace ambiguous or overlapping identity targeting with an explainable precedence model. + +- Make the complete business decision process configurable without modifying source code. + +- Provide repeatable, idempotent processing. + +- Provide safe read-only evaluation using -WhatIf. + +- Minimize privileges assigned to the production automation identity. + +- Provide evidence suitable for troubleshooting, audit, validation, and change review. + +- Support local, offline unit testing with synthetic users. + +- Support future modules for additional Entra identity object types without redesigning the user rule engine. + + + +Non-objectives for version 1: + + + +- Processing service principals. + +- Processing managed identities. + +- Processing non-user workload identities. + +- Processing agentic identities that are not represented as Entra user objects. + +- Replacing Conditional Access. + +- Building a graphical web application. + +- Allowing manual persona assignment outside the rule engine. + +- Storing tenant-specific proprietary values in source code. + + + +====================================================================== + +4. APPROVED SCOPE + +====================================================================== + + + +4.1 Initial identity scope + + + +Version 1 processes Microsoft Entra user objects only. + + + +Future releases may add separate data-provider and evaluation modules for: + + + +- Service principals + +- Managed identities + +- Workload identities + +- Agentic identities + + + +The version 1 architecture must not assume that all future identity types share user-object properties. + + + +4.2 Tenant and development scope + + + +- The connected environment is the production tenant. + +- Early connected development and testing will use read-only permissions. + +- Local development using PowerShell 7 is approved for the project owner. + +- Offline unit testing must use synthetic user and membership objects and must not require tenant connectivity. + +- One production Azure Automation account/managed identity will be used. + +- A separate production write-capable identity is not required. + +- Write permissions will not be granted during the initial read-only development stage. + + + +4.3 Configuration scope + + + +- JSON is the only supported configuration format for version 1. + +- The JSON file represents the entire ordered decision process. + +- Business rules, precedence, operators, target attribute, logging, summary interval, and supported runtime behavior are externally configurable. + +- Tenant-specific parameters must not be embedded in the PowerShell source. + + + +====================================================================== + +5. CORE DESIGN PRINCIPLES + +====================================================================== + + + +5.1 Deterministic + + + +Given the same normalized user data, related identity data, configuration version, and rule order, the engine must always produce the same result. + + + +5.2 Exactly one result + + + +Each successfully evaluated user receives exactly one calculated result: + + + +- A persona produced by the first matching rule, or + +- Unclassified when no enabled rule matches. + + + +5.3 First match wins + + + +- Rules are evaluated in ascending numeric priority order. + +- Lower numeric values have higher precedence. + +- Evaluation for the current user stops immediately after the first successful rule match. + +- Lower-priority rules are not evaluated after a match. + +- In diagnostic testing, an optional non-production analysis mode may evaluate all rules to detect overlaps, but this must not alter the authoritative first-match result. + + + +5.4 Idempotent + + + +- Every run recomputes the persona from authoritative inputs. + +- The attribute is updated only when the calculated value differs from the current value. + +- Repeated runs with unchanged inputs produce no directory writes. + + + +5.5 Configuration-driven + + + +- The script contains generic rule-processing logic. + +- The JSON contains tenant-specific business decisions. + +- No persona-specific business logic is hard-coded in the engine. + +- Immutable account Object IDs, protected group Object IDs, role mappings, and property patterns belong in rules or referenced configuration objects. + + + +5.6 Fail safe + + + +The engine must not write a lower-confidence result when required data cannot be retrieved or evaluated. + + + +5.7 Explainable + + + +Every user result must identify: + + + +- Calculated persona + +- Matched rule ID and name, if any + +- Rule priority + +- Existing persona + +- Proposed or completed write action + +- Evaluation status + +- UPN + +- Account Object ID + +- Run correlation ID + + + +5.8 Modular + + + +Authentication, data retrieval, normalization, rule evaluation, persistence, presentation, configuration, and auditing must remain separable components. + + + +====================================================================== + +6. TERMINOLOGY + +====================================================================== + + + +Persona: + +A deterministic identity classification value produced by the rule engine. + + + +Business rule: + +An ordered definition containing a resulting persona and one or more conditions. + + + +Condition: + +A comparison against a normalized user property, membership result, role result, configured Object ID collection, or other supported data source. + + + +Condition group: + +A logical All or Any block containing conditions and/or nested condition groups. + + + +Unclassified: + +Evaluation completed successfully, but no enabled business rule matched. + + + +EvaluationError: + +The engine could not reliably finish evaluating the user because required data, configuration, or processing was unavailable or invalid. + + + +WhatIf: + +Native PowerShell risk-mitigation behavior that evaluates and reports intended changes without issuing Microsoft Graph write requests. + + + +Account Object ID: + +The immutable Entra object identifier for the user account. + + + +UPN: + +The current userPrincipalName value. UPN is required in project logs even though it may change over time. + + + +====================================================================== + +7. FUNCTIONAL REQUIREMENTS + +====================================================================== + + + +FR-001 - Load configuration + + + +The engine must load a specified JSON configuration file. + + + +FR-002 - Validate before processing + + + +The engine must validate JSON syntax, schema, semantics, and safety constraints before connecting or processing users. A configuration with errors must not be used. + + + +FR-003 - Authenticate + + + +The solution must support: + + + +- Interactive/delegated authentication for approved local development. + +- Managed identity authentication for Azure Automation. + + + +Authentication logic must be isolated behind an adapter or dedicated function/module. + + + +FR-004 - Enumerate all users + + + +The production run must support enumeration of all in-scope Entra user accounts, including pagination. + + + +FR-005 - Select required properties + + + +The engine must retrieve the properties required by enabled rules plus operational fields required for logging and updates. The implementation should avoid retrieving unused properties where practical. + + + +Initial supported user properties include: + + + +- id + +- userPrincipalName + +- displayName, if enabled for diagnostics + +- userType + +- accountEnabled + +- companyName + +- jobTitle + +- department + +- configured persona attribute + + + +FR-006 - Retrieve related data + + + +The engine must retrieve and cache related data required by enabled rules, including configured forms of group membership and directory-role information. + + + +FR-007 - Normalize data + + + +Raw Microsoft Graph responses must be converted to normalized internal objects before evaluation. + + + +FR-008 - Evaluate ordered rules + + + +Rules must be sorted by priority and evaluated in that order. + + + +FR-009 - Stop after first match + + + +The authoritative evaluation must stop after the first matching rule. + + + +FR-010 - Unclassified result + + + +If all enabled rules are evaluated successfully and none match, the calculated persona must be Unclassified. + + + +FR-011 - Disabled accounts + + + +Disabled accounts remain in scope and are evaluated normally. accountEnabled is logged and may be used by future or configured rules. + + + +FR-012 - Null handling + + + +A null or absent optional property is treated as empty for ordinary string comparisons. If it does not match the requested value, the condition evaluates false. It is not an evaluation failure. + + + +Dedicated IsNull and IsNotNull operators provide intentional null matching. + + + +FR-013 - Group-data failure + + + +If required group data cannot be reliably retrieved for a user or rule, the affected user must receive EvaluationError. The engine must not assume that an unknown membership result is false. + + + +FR-014 - Preserve current value on evaluation failure + + + +If a user receives EvaluationError, the engine must preserve the current persona attribute and perform no write for that user. + + + +FR-015 - Compare current and calculated values + + + +The engine must compare the existing persona with the calculated persona before persistence. + + + +FR-016 - Write changed values only + + + +A production write occurs only if: + + + +- Evaluation completed successfully. + +- The calculated value differs from the existing value. + +- The target attribute is valid and approved. + +- -WhatIf is not active. + +- The operation passes ShouldProcess. + + + +FR-017 - WhatIf safety + + + +When -WhatIf is active: + + + +- Read operations continue. + +- Rules are evaluated normally. + +- Existing and calculated values are compared. + +- Intended updates are reported as WouldUpdate. + +- No Microsoft Graph PATCH or other write request is issued. + +- Logs and summaries are still produced. + + + +FR-018 - Real-time console output + + + +Immediately after each user is processed, the script must display the result on screen. + + + +FR-019 - Periodic summary + + + +After every configured number of processed users, the script must display a table showing all business rules and counts. + + + +FR-020 - Summary interval semantics + + + +- Default summary interval: 25 + +- A value greater than zero displays a summary after each interval. + +- A value of zero suppresses interim summaries. + +- A final summary is always displayed. + + + +FR-021 - Final reconciliation + + + +At each summary, the engine must verify: + + + + Processed = Matched + Unclassified + EvaluationError + + + +A failed reconciliation must be logged as an engine defect/error. + + + +FR-022 - Structured logs + + + +The engine must produce structured audit records suitable for file output and future ingestion into an approved logging platform. + + + +FR-023 - Configuration editor + + + +The project must include a second script that validates and interactively edits the JSON configuration. + + + +FR-024 - Noninteractive validation + + + +The configuration script must support noninteractive validation for Azure DevOps pipelines and return a nonzero process exit code when validation fails. + + + +FR-025 - Configuration test data + + + +The configuration editor must support testing rules against synthetic sample users without connecting to the tenant. + + + +FR-026 - Backup before save + + + +Interactive edits must be validated before save and should create a timestamped backup or save-as output before replacing an existing configuration. + + + +====================================================================== + +8. RULE ENGINE SPECIFICATION + +====================================================================== + + + +8.1 Rule ordering + + + +Each rule must contain a unique numeric priority. The proposed convention is that lower numeric values are evaluated first. + + + +8.2 Required rule fields + + + +Each rule requires: + + + +- id + +- name + +- description + +- enabled + +- priority + +- persona + +- match + + + +Optional fields may include: + + + +- tags + +- owner + +- changeReference + +- effectiveDate + +- notes + +- testCases + + + +8.3 Logical composition + + + +Version 1 supports: + + + +- all: all child items must evaluate true. + +- any: at least one child item must evaluate true. + +- Nested all and any groups. + + + +Maximum logical nesting depth is configurable through the JSON and editor. + + + +Recommended defaults and guardrails: + + + +- Default maximumConditionDepth: 5 + +- Minimum supported value: 1 + +- Hard software ceiling: 10 + + + +The runtime validator and editor must reject configurations exceeding the configured limit or software ceiling. + + + +8.4 Initial operators + + + +- equals + +- notEquals + +- contains + +- notContains + +- startsWith + +- endsWith + +- matchesRegex + +- in + +- notIn + +- isNull + +- isNotNull + +- memberOf + +- notMemberOf + + + +8.5 String comparison + + + +- Case-insensitive by default. + +- A future condition-level caseSensitive flag may be supported. + +- Null values are treated as empty for ordinary string comparisons. + +- Regex patterns must be validated before execution. + + + +8.6 Group membership + + + +Membership mode is configurable per condition: + + + +- direct + +- transitive + + + +A rule may combine group membership with user properties using nested All/Any logic. + + + +8.7 Role and privilege sources + + + +The architecture must allow any configured combination of: + + + +- Security-group membership + +- Active directory-role assignments + +- Eligible role information, if authorized and implemented + +- Other approved identity sources added through data-provider modules + + + +The first matching rule still determines the persona. + + + +8.8 Immutable account rules + + + +Special accounts, such as emergency-access accounts, are identified through immutable user Object IDs configured within normal business-rule definitions. The engine must not include a separate hard-coded classification path. + + + +8.9 Candidate persona catalogue + + + +The following are candidate business classifications, not hard-coded engine behavior: + + + +- Guest + +- BreakGlass-Admin + +- Tier0-Admin + +- Tier1-Admin + +- Tier2-Admin + +- Restricted-User + +- Test-Account + +- Service-Account + +- Shared-Functional-Account + +- Meeting-Room-Device + +- Employee + +- Contractor + +- Student + + + +Future modules may add: + + + +- Identity-Workload + +- Agentic-Account + + + +Unclassified is a processing result when no rule matches. EvaluationError is an execution result and must not be treated as a normal persona rule. + + + +====================================================================== + +9. EXAMPLE SANITIZED CONFIGURATION + +====================================================================== + + + +The following is illustrative. The developer must create and enforce a formal JSON Schema. + + + +{ + + "schemaVersion": "1.0", + + "configurationVersion": "0.1.0", + + "environment": "Production", + + "tenant": { + + "tenantId": "" + + }, + + "engine": { + + "summaryInterval": 25, + + "maximumConditionDepth": 5, + + "stopAfterFirstMatch": true, + + "defaultNoMatchPersona": "Unclassified", + + "preserveExistingValueOnEvaluationError": true + + }, + + "targetAttribute": { + + "name": "", + + "approvedWritableAttributes": [ + + "" + + ] + + }, + + "dataSources": { + + "users": { + + "enabled": true + + }, + + "groups": { + + "enabled": true, + + "supportedMembershipModes": [ + + "direct", + + "transitive" + + ] + + }, + + "directoryRoles": { + + "enabled": false + + } + + }, + + "logging": { + + "consoleLevel": "Normal", + + "structuredLogLevel": "Information", + + "includeUserPrincipalName": true, + + "includeAccountObjectId": true, + + "includeConditionTrace": false, + + "outputPath": "" + + }, + + "rules": [ + + { + + "id": "PER-010", + + "name": "Emergency Administrator", + + "description": "Matches configured emergency-access user Object IDs.", + + "enabled": true, + + "priority": 10, + + "persona": "BreakGlass-Admin", + + "match": { + + "all": [ + + { + + "source": "user", + + "property": "id", + + "operator": "in", + + "values": [ + + "", + + "" + + ] + + } + + ] + + } + + }, + + { + + "id": "PER-200", + + "name": "Restricted Employee", + + "description": "Example combining membership and user properties.", + + "enabled": true, + + "priority": 200, + + "persona": "Restricted-User", + + "match": { + + "all": [ + + { + + "source": "group", + + "membership": "transitive", + + "operator": "memberOf", + + "groupObjectIds": [ + + "" + + ] + + }, + + { + + "source": "user", + + "property": "companyName", + + "operator": "contains", + + "value": "" + + } + + ] + + } + + }, + + { + + "id": "PER-800", + + "name": "Employee", + + "description": "Example employee property pattern.", + + "enabled": true, + + "priority": 800, + + "persona": "Employee", + + "match": { + + "all": [ + + { + + "source": "user", + + "property": "companyName", + + "operator": "equals", + + "value": "" + + }, + + { + + "source": "user", + + "property": "userPrincipalName", + + "operator": "endsWith", + + "value": "@" + + } + + ] + + } + + } + + ] + +} + + + +====================================================================== + +10. CONFIGURATION VALIDATION REQUIREMENTS + +====================================================================== + + + +Validation has four layers. + + + +10.1 JSON syntax validation + + + +Detect at minimum: + + + +- Invalid braces or brackets + +- Invalid commas + +- Malformed JSON + +- Invalid encoding + +- Unreadable file + + + +10.2 JSON Schema validation + + + +Detect at minimum: + + + +- Missing required fields + +- Unsupported schema version + +- Incorrect data types + +- Invalid enum values + +- Unsupported operators + +- Invalid console/logging levels + +- Negative summary interval + +- Invalid GUID format where a GUID is required + +- Empty condition groups + +- Missing rule persona + +- Nesting values outside supported range + + + +10.3 Semantic validation + + + +Detect at minimum: + + + +- Duplicate rule IDs + +- Duplicate priorities + +- No enabled rules + +- Invalid or blank target attribute + +- Target attribute not present in approvedWritableAttributes + +- Rule references an unavailable data source + +- memberOf without group Object IDs + +- in/notIn without values + +- isNull/isNotNull incorrectly containing a comparison value + +- Rule producing an undefined or prohibited persona value + +- Unclassified used as an ordinary business-rule persona, unless explicitly approved later + +- Condition depth exceeding configured maximum + +- Configured maximum exceeding hard software ceiling + +- Requested group mode not enabled globally + +- Unsupported property name + +- Invalid regular expression + +- Circular references if reusable rule fragments are added later + + + +10.4 Safety validation + + + +Detect at minimum: + + + +- Production-capable configuration with blank target attribute + +- Unsupported writable attribute + +- Enabled group rules while group retrieval is disabled + +- Configuration version downgrade where policy prohibits it + +- Rule deletion or reorder without a configuration version change, if enforcement is enabled + +- Structured condition tracing enabled without explicit acknowledgement + +- Save path overwriting the only valid configuration without backup + + + +10.5 Validation results + + + +Findings must contain: + + + +- Severity: Error, Warning, Information + +- JSON path or rule ID + +- Finding code + +- Clear description + +- Suggested resolution + + + +Errors block execution and saving. Warnings require acknowledgement in the interactive editor but do not necessarily block validation-only mode unless configured to treat warnings as errors. + + + +====================================================================== + +11. SCRIPT 1: PERSONA ENGINE + +====================================================================== + + + +Proposed file: + + + + Invoke-PersonaEngine.ps1 + + + +11.1 Proposed parameter surface + + + +- -ConfigPath , required + +- -WhatIf, native PowerShell common risk-mitigation parameter + +- -Verbose, native common parameter + +- -Debug, native diagnostic common parameter only + +- -UserObjectId , optional single-user test execution + +- -OutputPath , optional override if permitted + +- -CorrelationId , optional supplied run identifier + + + +The script should use CmdletBinding with SupportsShouldProcess. + + + +11.2 WhatIf implementation requirement + + + +- Use ShouldProcess for write operations. + +- Ensure the persistence function is not invoked when ShouldProcess returns false. + +- Unit tests must prove that the Microsoft Graph write adapter receives zero calls under -WhatIf. + +- -Debug must not be overloaded to mean read-only mode. + + + +11.3 Suggested execution modes + + + +Read-only evaluation: + + + + ./Invoke-PersonaEngine.ps1 -ConfigPath ./config/persona-engine.json -WhatIf + + + +Read-only with operational detail: + + + + ./Invoke-PersonaEngine.ps1 -ConfigPath ./config/persona-engine.json -WhatIf -Verbose + + + +Read-only with developer diagnostics: + + + + ./Invoke-PersonaEngine.ps1 -ConfigPath ./config/persona-engine.json -WhatIf -Debug + + + +Production changed-values-only processing: + + + + ./Invoke-PersonaEngine.ps1 -ConfigPath ./config/persona-engine.json + + + +Single-user validation: + + + + ./Invoke-PersonaEngine.ps1 -ConfigPath ./config/persona-engine.json -UserObjectId -WhatIf + + + +11.4 Exit codes + + + +Proposed: + + + +- 0: Successful run; no fatal processing errors + +- 1: Configuration validation failure + +- 2: Authentication/authorization failure + +- 3: User enumeration failure + +- 4: Fatal required data-provider failure + +- 5: Reconciliation failure + +- 6: Unexpected fatal engine error + + + +Per-user EvaluationError does not necessarily terminate the entire run, but final run status must report the number of affected accounts and may use a configurable warning/failure threshold. + + + +====================================================================== + +12. SCRIPT 2: CONFIGURATION MANAGER + +====================================================================== + + + +Proposed file: + + + + Edit-PersonaEngineConfig.ps1 + + + +12.1 Purposes + + + +- Validate configuration syntax. + +- Validate against JSON Schema. + +- Validate semantic relationships. + +- Validate safety constraints. + +- Interactively edit engine settings. + +- Interactively create, clone, modify, enable, disable, reorder, and remove rules. + +- Test rules using synthetic sample users. + +- Display effective rule order. + +- Revalidate changes before save. + +- Produce a concise change summary. + +- Support noninteractive pipeline validation. + + + +12.2 Proposed parameters + + + +- -ConfigPath , required + +- -ValidateOnly + +- -NonInteractive + +- -SchemaPath , optional override + +- -OutputPath , optional save-as target + +- -TreatWarningsAsErrors + +- -TestDataPath , optional synthetic sample input + + + +12.3 Example usage + + + +Validate only: + + + + ./Edit-PersonaEngineConfig.ps1 -ConfigPath ./config/persona-engine.json -ValidateOnly + + + +Pipeline validation: + + + + ./Edit-PersonaEngineConfig.ps1 -ConfigPath ./config/persona-engine.json -ValidateOnly -NonInteractive + + + +Interactive editor: + + + + ./Edit-PersonaEngineConfig.ps1 -ConfigPath ./config/persona-engine.json + + + +12.4 Interactive menu + + + +The initial editor should provide functions equivalent to: + + + +1. Edit engine settings + +2. Edit logging settings + +3. Edit identity data sources + +4. List business rules + +5. Add business rule + +6. Edit business rule + +7. Clone business rule + +8. Enable or disable business rule + +9. Reorder rule priority + +10. Delete business rule + +11. Validate configuration + +12. Show effective rule order + +13. Test rules against sample users + +14. Compare with another configuration + +15. Save or Save As + +16. Quit + + + +12.5 Save behavior + + + +Before saving: + + + +- Re-run all validation layers. + +- Block save on errors. + +- Display warnings. + +- Show a change summary. + +- Increment or request an updated configuration version. + +- Create a timestamped backup when overwriting an existing file. + +- Write safely, preferably through a temporary file followed by an atomic replace where supported. + + + +====================================================================== + +13. OUTPUT AND LOGGING SPECIFICATION + +====================================================================== + + + +13.1 Required identity fields + + + +User-level logs must include: + + + +- userPrincipalName + +- accountObjectId + + + +13.2 Run-level fields + + + +Include at minimum: + + + +- timestampUtc + +- runId + +- scriptVersion + +- configurationVersion + +- configurationSchemaVersion + +- configurationFileHash + +- executionMode + +- PowerShellVersion + +- authenticationMode + +- tenantId or approved tenant placeholder/reference + +- caller or managed identity Object ID where available + +- startTimeUtc + +- completionTimeUtc + +- elapsedMilliseconds + +- totalUsersRetrieved + +- totalUsersProcessed + +- summaryInterval + +- enabledRuleCount + +- disabledRuleCount + +- matchedCount + +- unclassifiedCount + +- evaluationErrorCount + +- wouldUpdateCount + +- updatedCount + +- unchangedCount + +- updateFailedCount + +- fatalErrorCount + +- exitCode + + + +13.3 User-level fields + + + +Include at minimum: + + + +- timestampUtc + +- runId + +- sequence + +- totalUsers + +- executionMode + +- userPrincipalName + +- accountObjectId + +- accountEnabled + +- existingPersona + +- calculatedPersona + +- matchedRuleId + +- matchedRuleName + +- matchedRulePriority + +- classificationStatus + +- writeStatus + +- evaluationDurationMs + +- retrievalRetryCount, if applicable + +- writeRetryCount, if applicable + +- errorCategory + +- errorCode + +- errorMessage + + + +13.4 Rule summary fields + + + +Include at minimum: + + + +- ruleId + +- ruleName + +- persona + +- priority + +- enabled + +- evaluatedCount + +- matchedCount + +- wouldUpdateCount + +- updatedCount + +- unchangedCount + +- errorCount + + + +13.5 Result states + + + +Classification status: + + + +- Matched + +- Unclassified + +- EvaluationError + + + +Write status: + + + +- NotRequired + +- WouldUpdate + +- Updated + +- Unchanged + +- SuppressedDueToEvaluationError + +- UpdateFailed + + + +13.6 Console detail levels + + + +Quiet: + + + +- Fatal errors + +- Final summary + + + +Normal: + + + +- One concise line per user + +- Interim summaries + +- Final summary + + + +Detailed: + + + +- Multi-line record per user + +- Interim summaries + +- Final summary + + + +Debug: + + + +- Condition-by-condition diagnostic trace + +- Must use native -Debug behavior + +- Should not be enabled by default for centralized production logs + + + +13.7 Example normal console line + + + +[000124/008912] WOULD UPDATE user@ [] Unclassified -> Employee [PER-800] 42 ms + + + +13.8 Example detailed console record + + + +[WHATIF][000124/008912] + +UPN: user@ + +Object ID: + +Result: MATCHED + +Rule: PER-800 / Employee + +Persona: Unclassified -> Employee + +Write: WOULD UPDATE + +Duration: 42 ms + + + +13.9 Example structured user event + + + +{ + + "timestampUtc": "", + + "runId": "", + + "sequence": 124, + + "totalUsers": 8912, + + "executionMode": "WhatIf", + + "userPrincipalName": "user@", + + "accountObjectId": "", + + "accountEnabled": true, + + "ruleId": "PER-800", + + "ruleName": "Employee", + + "calculatedPersona": "Employee", + + "existingPersona": "Unclassified", + + "classificationStatus": "Matched", + + "writeStatus": "WouldUpdate", + + "evaluationDurationMs": 42, + + "message": "Rule matched; update suppressed by WhatIf" + +} + + + +13.10 Periodic summary example + + + +Processed: 50 of 8,912 + +Elapsed: 00:00:18 + +Mode: WHATIF / READ-ONLY + + + +Rule ID Priority Persona Matched Would Update Unchanged Errors + +------- -------- ------------------- ------- ------------ --------- ------ + +PER-010 10 BreakGlass-Admin 2 0 2 0 + +PER-020 20 Tier0-Admin 5 1 4 0 + +PER-100 100 Guest 11 3 8 0 + +PER-800 800 Employee 27 8 19 0 + +N/A N/A Unclassified 5 2 3 0 + + + +====================================================================== + +14. SECURITY AND AUTHORIZATION REQUIREMENTS + +====================================================================== + + + +14.1 Authentication + + + +- Azure Automation uses a managed identity. + +- Local connected development uses an approved interactive or read-only application identity. + +- No client secret should be stored in source control. + + + +14.2 Read permissions + + + +The execution identity requires only the permissions needed to retrieve: + + + +- In-scope user properties + +- Configured group membership data + +- Configured role data, when enabled + +- Existing persona value + + + +Exact Microsoft Graph permissions must be selected and documented during technical design based on the final Graph endpoints and property model. + + + +14.3 Write permissions + + + +The production identity must be granted the minimum permission required to update the configured target persona attribute. + + + +The technical design must verify whether Entra authorization can enforce write scope at the individual attribute level for the selected attribute mechanism. This must not be assumed. + + + +If the selected Microsoft Graph permission grants broader user-write capability than the single target attribute, implement compensating controls: + + + +- The persistence module accepts only the approved target attribute. + +- The target attribute must be present in approvedWritableAttributes. + +- Configuration validation rejects all other attributes. + +- The Graph request body is generated by a dedicated function that includes only the target attribute. + +- Unit and integration tests inspect the request body. + +- Code owners approve changes to persistence code and writable-attribute configuration. + +- Production branch policies prevent unreviewed changes. + +- Graph/directory audit logs are monitored for unexpected property writes by the automation identity. + +- -WhatIf is used for impact analysis before enforcement changes. + +- A kill switch or ability to disable the automation schedule is documented. + + + +14.4 Data handling + + + +- UPN and Account Object ID are approved for project logs. + +- Do not log access tokens, authorization headers, secrets, or full Graph responses. + +- Do not log every property value by default. + +- Detailed condition values are diagnostic-only and controlled through native -Debug/configuration. + +- Synthetic test data must not contain real user information. + + + +14.5 Source control + + + +- No real tenant ID, domain, user Object ID, group Object ID, or production attribute value in public or reusable examples. + +- Tenant-specific configuration must be stored in an appropriately protected repository/location. + +- Pull requests and code review are required for production changes. + + + +====================================================================== + +15. PROPOSED ARCHITECTURE + +====================================================================== + + + +Invoke-PersonaEngine.ps1 + +| + ++-- Configuration + +| +-- Import-PersonaConfiguration + +| +-- Test-PersonaConfiguration + +| +-- Resolve-TargetAttribute + +| + ++-- Authentication + +| +-- Connect-PersonaGraphInteractive + +| +-- Connect-PersonaGraphManagedIdentity + +| + ++-- Data Providers + +| +-- Get-PersonaUsers + +| +-- Get-PersonaGroupMembership + +| +-- Get-PersonaDirectoryRoles + +| +-- Future: Get-PersonaWorkloadIdentities + +| + ++-- Normalization + +| +-- ConvertTo-PersonaUserRecord + +| +-- ConvertTo-PersonaMembershipRecord + +| + ++-- Rule Engine + +| +-- Test-PersonaCondition + +| +-- Test-PersonaConditionGroup + +| +-- Test-PersonaRule + +| +-- Resolve-UserPersona + +| + ++-- Persistence + +| +-- Compare-PersonaValue + +| +-- Set-UserPersonaAttribute + +| + ++-- Presentation + +| +-- Write-UserPersonaResult + +| +-- Write-PersonaSummary + +| + ++-- Audit + + +-- New-PersonaAuditRecord + + +-- Export-PersonaRunReport + + + +Edit-PersonaEngineConfig.ps1 + +| + ++-- Configuration Import + ++-- JSON Schema Validation + ++-- Semantic Validation + ++-- Safety Validation + ++-- Interactive Menus + ++-- Rule Editor + ++-- Sample User Test Harness + ++-- Change Comparison + ++-- Safe Save and Backup + + + +Critical flow: + + + +Graph acquisition + + -> normalized identity record + + -> pure rule engine + + -> persona decision result + + -> comparison + + -> optional persistence adapter + + -> console and structured audit output + + + +The pure rule engine must not depend on Graph authentication, Azure Automation, or console rendering. + + + +====================================================================== + +16. REPOSITORY STRUCTURE + +====================================================================== + + + +PersonaEngine/ + +|-- README.md + +|-- Invoke-PersonaEngine.ps1 + +|-- Edit-PersonaEngineConfig.ps1 + +|-- PersonaEngine.psd1 + +|-- PersonaEngine.psm1 + +| + +|-- config/ + +| |-- persona-engine.example.json + +| |-- persona-engine.schema.json + +| + +|-- src/ + +| |-- Authentication/ + +| |-- Configuration/ + +| |-- DataProviders/ + +| |-- Normalization/ + +| |-- RuleEngine/ + +| |-- Persistence/ + +| |-- Presentation/ + +| |-- Audit/ + +| + +|-- tests/ + +| |-- Unit/ + +| |-- Integration/ + +| |-- Configuration/ + +| |-- Safety/ + +| |-- TestData/ + +| + +|-- docs/ + +| |-- Architecture.md + +| |-- BusinessRules.md + +| |-- ConfigurationReference.md + +| |-- Logging.md + +| |-- SecurityModel.md + +| |-- OperationsRunbook.md + +| + +|-- pipelines/ + +| |-- validate.yml + +| |-- test.yml + +| |-- release.yml + +| + +|-- specs/ + + |-- 001-persona-engine/ + + |-- spec.md + + |-- plan.md + + |-- tasks.md + + |-- research.md + + |-- data-model.md + + |-- quickstart.md + + |-- contracts/ + + |-- checklists/ + + + +====================================================================== + +17. DEVELOPMENT PLAN + +====================================================================== + + + +Phase 0 - Requirements and governance + + + +Deliverables: + + + +- Approved requirements baseline + +- Decision register + +- Initial security model + +- Initial scope and non-scope + +- Initial candidate persona catalogue + +- Open risks and assumptions + + + +Exit criteria: + + + +- Core behavior is agreed. + +- WhatIf behavior is agreed. + +- Configuration editor is in scope. + +- User-object-only version 1 scope is agreed. + + + +Phase 1 - Spec Kit specification + + + +Deliverables: + + + +- spec.md + +- User stories + +- Functional requirements + +- Nonfunctional requirements + +- Acceptance scenarios + +- Edge cases + +- Clarification register + + + +Primary user stories: + + + +1. As an identity administrator, I can run the engine in WhatIf mode and see the persona that would be assigned to each user without modifying Entra ID. + +2. As a security engineer, I can define ordered business rules in JSON without modifying PowerShell. + +3. As an operator, I can see each user result immediately and receive periodic summaries. + +4. As a configuration owner, I can validate and interactively edit rules. + +5. As a pipeline owner, I can block invalid configurations noninteractively. + +6. As an auditor, I can correlate each result to a UPN, Account Object ID, rule, configuration version, and run ID. + + + +Phase 2 - Technical plan and research + + + +Deliverables: + + + +- plan.md + +- research.md + +- Authentication design + +- Microsoft Graph endpoint and permission matrix + +- Target attribute technical decision + +- Paging, throttling, and retry design + +- JSON Schema design + +- Logging destination design + +- Azure Automation compatibility validation + +- Module dependency decisions + + + +Mandatory technical research item: + + + +Determine the selected persona attribute mechanism and document the exact authorization boundary for updating it. If individual-attribute authorization is unavailable, document compensating controls before implementation approval. + + + +Phase 3 - Data model and contracts + + + +Deliverables: + + + +- data-model.md + +- persona-engine.schema.json + +- Internal PowerShell object contracts + +- Audit-event schema + +- Exit-code contract + +- Configuration sample + +- Synthetic user test-data schema + + + +Phase 4 - Task decomposition + + + +Deliverables: + + + +- tasks.md + +- Dependency ordering + +- Parallelizable tasks + +- Definition of done per task + +- Security-review tasks + +- Pipeline tasks + +- Documentation tasks + + + +Phase 5 - Implementation foundation + + + +Tasks: + + + +- Repository scaffolding + +- Module manifest + +- Configuration import + +- JSON Schema validation + +- Semantic validator + +- Safety validator + +- Normalized internal object types + +- Initial Pester framework + +- Synthetic test fixtures + + + +Phase 6 - Rule engine + + + +Tasks: + + + +- Condition operator implementation + +- Nested All/Any implementation + +- Maximum-depth enforcement + +- Null handling + +- Rule ordering + +- First-match stop behavior + +- Unclassified behavior + +- EvaluationError behavior + +- Rule counters + +- Pure offline tests + + + +Phase 7 - Microsoft Graph adapters + + + +Tasks: + + + +- Interactive authentication adapter + +- Managed identity adapter + +- User enumeration and paging + +- Property selection + +- Group membership provider + +- Role provider interface + +- Retry/throttling handling + +- Data normalization + + + +Phase 8 - Persistence and WhatIf + + + +Tasks: + + + +- Current-value comparison + +- Dedicated one-attribute request builder + +- ShouldProcess implementation + +- WhatIf zero-write tests + +- Changed-values-only processing + +- Error handling + +- Preserve-on-error behavior + + + +Phase 9 - Presentation and audit + + + +Tasks: + + + +- One-line user output + +- Detailed output + +- Native Verbose and Debug output + +- Interim summary interval + +- Final summary + +- Reconciliation check + +- Structured JSON logs + +- Run-level event + +- User-level event + +- Rule-level summary + + + +Phase 10 - Configuration manager + + + +Tasks: + + + +- Validate-only mode + +- Noninteractive mode + +- Main menu + +- Settings editor + +- Rule list and editor + +- Nested condition editor + +- Clone/enable/disable/delete/reorder + +- Sample-user testing + +- Compare configurations + +- Safe save and backup + +- Pipeline return codes + + + +Phase 11 - Integration and operational testing + + + +Tasks: + + + +- Read-only production-tenant testing + +- Small controlled user set + +- WhatIf full-tenant run + +- Summary reconciliation + +- Permission-denial tests + +- Group lookup failure tests + +- Throttling/retry tests + +- Malformed configuration tests + +- Performance characterization + +- Azure Automation execution tests + + + +Phase 12 - Production release + + + +Tasks: + + + +- Security review + +- Code review + +- Configuration review + +- Grant approved production write permission + +- WhatIf evidence review + +- Controlled enforcement run + +- Verify only the approved attribute changed + +- Enable schedule + +- Monitor logs and directory audit events + +- Document rollback and kill switch + + + +====================================================================== + +18. TEST STRATEGY + +====================================================================== + + + +18.1 Unit tests + + + +Test at minimum: + + + +- Each comparison operator + +- Case-insensitive string behavior + +- Null handling + +- isNull and isNotNull + +- Regex validation and matching + +- in and notIn + +- Direct and transitive membership result handling + +- All groups + +- Any groups + +- Nested groups + +- Maximum depth + +- Rule priority sorting + +- First-match stop + +- Unclassified result + +- EvaluationError result + +- Disabled account evaluation + +- Existing-value comparison + +- Rule counters + +- Summary reconciliation + + + +18.2 Configuration tests + + + +Test at minimum: + + + +- Valid configuration + +- Malformed JSON + +- Schema violations + +- Duplicate rule IDs + +- Duplicate priorities + +- Unsupported operator + +- Unsupported property + +- Invalid GUID + +- Empty group list + +- Disabled required data source + +- Invalid regex + +- Excessive nesting + +- Blank target attribute + +- Unapproved target attribute + +- Version behavior + + + +18.3 Safety tests + + + +Test at minimum: + + + +- WhatIf issues zero Graph write calls. + +- EvaluationError issues zero write calls. + +- Unchanged value issues zero write calls. + +- Request body contains only the approved attribute. + +- Invalid target attribute blocks execution before user processing. + +- No token or authorization header appears in logs. + +- Unexpected Graph response does not produce an unsafe update. + + + +18.4 Integration tests + + + +Test at minimum: + + + +- Interactive read-only authentication + +- Managed identity authentication + +- User pagination + +- User property retrieval + +- Direct membership + +- Transitive membership + +- Required data-provider failure + +- Retryable Graph response handling + +- Non-retryable Graph response handling + +- Single-user WhatIf + +- Full-run WhatIf + +- Controlled write to test account after approval + + + +18.5 Configuration editor tests + + + +Test at minimum: + + + +- Validate-only success and failure exit codes + +- Noninteractive execution + +- Add/edit/clone/delete/reorder rule + +- Nested condition editing + +- Maximum-depth guardrail + +- Validation before save + +- Backup creation + +- Configuration comparison + +- Synthetic user rule testing + + + +18.6 Acceptance test examples + + + +Scenario A - First match wins + + + +Given a user matches rule priority 100 and rule priority 800, + +When the engine evaluates the user, + +Then priority 100 determines the persona, + +And priority 800 is not evaluated in authoritative mode. + + + +Scenario B - No match + + + +Given all required data is available, + +And no enabled rule matches, + +When evaluation completes, + +Then calculatedPersona is Unclassified, + +And classificationStatus is Unclassified. + + + +Scenario C - Required group lookup fails + + + +Given a rule requires group membership, + +And membership cannot be retrieved reliably, + +When that user is evaluated, + +Then classificationStatus is EvaluationError, + +And the existing persona is preserved, + +And no write is attempted. + + + +Scenario D - WhatIf + + + +Given the existing persona differs from the calculated persona, + +When the engine runs with -WhatIf, + +Then writeStatus is WouldUpdate, + +And no Microsoft Graph write request is issued. + + + +Scenario E - Unchanged + + + +Given the existing persona equals the calculated persona, + +When the user is processed, + +Then writeStatus is Unchanged, + +And no write is attempted. + + + +Scenario F - Periodic summary + + + +Given summaryInterval is 25, + +When 50 users have been processed, + +Then summaries are displayed after users 25 and 50, + +And a final summary is displayed at completion. + + + +Scenario G - Final-only summary + + + +Given summaryInterval is 0, + +When users are processed, + +Then no interim summary is displayed, + +And the final summary is displayed. + + + +====================================================================== + +19. NONFUNCTIONAL REQUIREMENTS + +====================================================================== + + + +NFR-001 - PowerShell version + + + +The runtime targets PowerShell 7 supported by the selected local and Azure Automation environments. + + + +NFR-002 - Performance + + + +- Display each result shortly after the user is evaluated. + +- Cache reusable group/role data where safe and practical. + +- Avoid retrieving the same static membership data repeatedly. + +- Record per-user and total duration. + +- Do not define an unsupported hard performance target until representative tenant testing is completed. + + + +NFR-003 - Reliability + + + +- Handle Microsoft Graph pagination. + +- Implement bounded retry with backoff for retryable responses. + +- Respect service-provided retry guidance when available. + +- Do not retry non-retryable authorization or validation failures indefinitely. + + + +NFR-004 - Maintainability + + + +- Public functions include comment-based help. + +- Business rules are not hard-coded. + +- Functions have focused responsibilities. + +- Rule evaluation remains independently testable. + + + +NFR-005 - Auditability + + + +- Every run receives a unique runId. + +- Every user event includes runId, UPN, and Account Object ID. + +- Configuration hash and version are recorded. + +- Every changed or proposed value identifies the matched rule. + + + +NFR-006 - Security + + + +- Least privilege. + +- Managed identity for automation. + +- No secrets in source control. + +- Only approved target attribute in write payload. + +- No write path under WhatIf. + + + +NFR-007 - Portability + + + +- Core rule engine and configuration validation run locally without Azure Automation. + +- Tenant access is isolated behind data-provider/authentication modules. + + + +NFR-008 - Compatibility + + + +- Avoid Windows PowerShell-only dependencies unless explicitly approved. + +- Verify all required modules in the Azure Automation PowerShell 7 environment. + + + +====================================================================== + +20. DEVOPS AND DELIVERY REQUIREMENTS + +====================================================================== + + + +20.1 Source control + + + +- Host the project in Azure DevOps Git. + +- Use feature branches and pull requests. + +- Protect the production/release branch. + +- Define code owners for persistence, security configuration, and production rules. + + + +20.2 Pipeline stages + + + +Proposed validation pipeline: + + + +1. Repository hygiene checks + +2. PowerShell static analysis + +3. JSON Schema validation + +4. Semantic/safety configuration validation + +5. Pester unit tests + +6. Pester safety tests + +7. Test result publication + +8. Package artifact creation + + + +Proposed release pipeline: + + + +1. Validate approved branch/tag + +2. Repeat validation and tests + +3. Package scripts/modules/config schema + +4. Deploy to Azure Automation + +5. Import required modules + +6. Publish runbook + +7. Keep schedule disabled until approval + +8. Execute WhatIf validation + +9. Approval gate + +10. Enable enforcement/schedule + + + +20.3 Change control + + + +Changes to the following require review: + + + +- Target attribute + +- approvedWritableAttributes + +- Rule priority + +- Rule enablement + +- Rule conditions + +- Persona outputs + +- Authentication permissions + +- Persistence functions + +- Logging destination + +- WhatIf/ShouldProcess behavior + + + +====================================================================== + +21. OPERATIONS MODEL + +====================================================================== + + + +21.1 Initial operating cadence + + + +A recurring Azure Automation schedule is intended. The exact frequency is deployment-configurable. A candidate starting cadence is hourly, subject to tenant size, operational requirements, and performance testing. + + + +21.2 Run workflow + + + +1. Start run and assign runId. + +2. Load and validate configuration. + +3. Authenticate. + +4. Determine enabled data requirements from the rules. + +5. Retrieve/cache required shared data. + +6. Enumerate users. + +7. Normalize one user. + +8. Evaluate ordered rules. + +9. Determine Matched, Unclassified, or EvaluationError. + +10. Compare current and calculated persona. + +11. Invoke ShouldProcess for a changed valid result. + +12. Update only the approved attribute when permitted. + +13. Write console and structured event. + +14. Display configured interim summaries. + +15. Reconcile totals. + +16. Display and log final summary. + +17. Return documented exit code. + + + +21.3 Kill switch + + + +At minimum, operations must be able to: + + + +- Disable the Azure Automation schedule. + +- Run with -WhatIf. + +- Revoke/remove production write permission if required. + +- Disable all write deployment stages. + + + +21.4 Rollback + + + +Because the engine recalculates values, rollback must be planned before enforcement. Options to evaluate during technical design: + + + +- Export the pre-change persona value for each updated user with runId. + +- Create a controlled restoration command/script using the run audit output. + +- Disable the schedule before restoration. + +- Require approval before mass restoration. + + + +The final rollback mechanism must be documented and tested before production enforcement. + + + +====================================================================== + +22. RISKS AND MITIGATIONS + +====================================================================== + + + +R-001 - Write permission broader than one attribute + + + +Risk: + +The selected Microsoft Graph permission may permit writes beyond the persona attribute. + + + +Mitigation: + +Verify the authorization model; use dedicated request builder, allowlist, tests, code review, audit monitoring, and managed identity. + + + +R-002 - Incorrect rule precedence + + + +Risk: + +A high-priority broad rule may prevent intended lower rules from executing. + + + +Mitigation: + +Effective-order display, synthetic tests, optional overlap analysis, pull-request review, and full WhatIf evidence. + + + +R-003 - Unknown group membership treated as false + + + +Risk: + +A retrieval failure could produce an incorrect lower-priority persona. + + + +Mitigation: + +Required group lookup failure produces EvaluationError and preserves the existing persona. + + + +R-004 - Configuration drift + + + +Risk: + +Runtime behavior changes without source-code changes. + + + +Mitigation: + +Version configuration, record file hash, validate in pipeline, protect production branch, and require review. + + + +R-005 - Excessive logging + + + +Risk: + +Condition traces could expose unnecessary identity data or create excessive volume. + + + +Mitigation: + +Normal logs capture result and matched rule; condition values require explicit diagnostic mode. + + + +R-006 - UPN changes + + + +Risk: + +UPN alone is not a stable identifier. + + + +Mitigation: + +Log both UPN and Account Object ID. + + + +R-007 - Full-tenant production development + + + +Risk: + +Testing against production data could cause unintended changes. + + + +Mitigation: + +Initial identity is read-only; offline synthetic tests; -WhatIf; single-user filtering; changed-values-only persistence; review gates. + + + +R-008 - Recursive configuration complexity + + + +Risk: + +Deep or malformed nested rules become difficult to validate and maintain. + + + +Mitigation: + +Configurable maximum depth, hard ceiling, editor enforcement, schema validation, and rule test cases. + + + +R-009 - Graph throttling or transient failure + + + +Risk: + +Large runs may encounter transient retrieval failures. + + + +Mitigation: + +Pagination, bounded retries, backoff, logging, caching, and no unsafe fallback assumptions. + + + +R-010 - Unclassified accounts overlooked + + + +Risk: + +No-match accounts may remain untreated. + + + +Mitigation: + +Explicit Unclassified result, dedicated summary row, logs, monitoring, and rule/data-quality review process. + + + +====================================================================== + +23. DECISION REGISTER + +====================================================================== + + + +D-001 - Persona is an enterprise identity classification with Conditional Access as the first consumer. APPROVED + +D-002 - Version 1 processes Entra users only. APPROVED + +D-003 - Future identity types are supported through modular providers/evaluators. APPROVED + +D-004 - One production Azure Automation identity/account is used. APPROVED + +D-005 - Initial connected development uses read-only permissions. APPROVED + +D-006 - Local PowerShell 7 development is approved for the project owner. APPROVED + +D-007 - The connected development environment is the production tenant. APPROVED + +D-008 - Offline synthetic testing is required. APPROVED + +D-009 - JSON is the only configuration format for version 1. APPROVED + +D-010 - The JSON contains the complete ordered decision model. APPROVED + +D-011 - First matching rule wins. APPROVED + +D-012 - Authoritative evaluation stops after the first match. APPROVED + +D-013 - Rules may combine user properties, groups, roles, and configured Object IDs. APPROVED + +D-014 - Direct/transitive membership is configurable per rule/condition. APPROVED + +D-015 - No-match result is Unclassified. APPROVED + +D-016 - EvaluationError is distinct from Unclassified. APPROVED + +D-017 - Disabled users continue to be classified normally. APPROVED + +D-018 - Null optional properties are empty/non-match, not failures. APPROVED + +D-019 - IsNull/IsNotNull support intentional null matching. APPROVED + +D-020 - Required group-data failure produces EvaluationError. APPROVED + +D-021 - Existing persona is preserved on EvaluationError. APPROVED + +D-022 - Nested All/Any logic is supported. APPROVED + +D-023 - Maximum condition nesting depth is configurable through JSON/editor. APPROVED + +D-024 - A hard software ceiling protects against excessive depth. APPROVED + +D-025 - Per-user output is displayed immediately. APPROVED + +D-026 - Interim rule summary interval is configurable. APPROVED + +D-027 - Default summary interval is 25. APPROVED + +D-028 - Summary interval 0 means final summary only. APPROVED + +D-029 - Final summary is always displayed. APPROVED + +D-030 - Logs include UPN. APPROVED + +D-031 - Logs include Account Object ID. APPROVED + +D-032 - Additional audit logging is desired. APPROVED + +D-033 - A second interactive configuration manager script is required. APPROVED + +D-034 - Configuration manager supports noninteractive validation. APPROVED + +D-035 - Native -WhatIf replaces the earlier custom read-only -Debug concept. APPROVED + +D-036 - Native -Debug remains developer diagnostics only. APPROVED + +D-037 - Writes occur only for changed valid persona values. APPROVED + +D-038 - The production identity should write only the configured attribute; technical enforcement must be verified. APPROVED REQUIREMENT / OPEN TECHNICAL VALIDATION + + + +====================================================================== + +24. OPEN TECHNICAL DECISIONS + +====================================================================== + + + +These are implementation research items, not unanswered business requirements. The developer/architect must document recommendations in research.md or architecture decision records. + + + +OTD-001 - Select the exact Entra persona attribute mechanism. + + + +Candidates may include an approved directory extension mechanism or another Entra-supported attribute consumable by the intended Conditional Access design. Confirm data type, Graph read/update method, discoverability, and Conditional Access compatibility. + + + +OTD-002 - Confirm exact Microsoft Graph permissions. + + + +Document least-privilege permissions for users, groups, directory roles, and the selected attribute. + + + +OTD-003 - Confirm whether write authorization can be restricted to the individual target attribute. + + + +If not, document compensating controls and obtain security approval. + + + +OTD-004 - Select Microsoft Graph access approach. + + + +Determine whether to use Microsoft Graph PowerShell SDK cmdlets, direct REST calls through authenticated Graph tooling, or a controlled combination. Consider Azure Automation module size, behavior, testability, and request-body control. + + + +OTD-005 - Select JSON Schema validation library/approach compatible with local PowerShell 7 and Azure Automation. + + + +OTD-006 - Select structured-log destination and transport. + + + +The format must remain independent enough to support local files and future centralized ingestion. + + + +OTD-007 - Define retry policy. + + + +Specify retryable status codes, maximum attempts, backoff, jitter, and logging. + + + +OTD-008 - Define full versus incremental processing roadmap. + + + +Version 1 may perform full enumeration. A future delta strategy may be considered only if it preserves deterministic behavior and periodic full reconciliation. + + + +OTD-009 - Define production schedule and concurrency lock. + + + +Prevent overlapping runs from writing conflicting values. + + + +OTD-010 - Define rollback implementation. + + + +Use pre-change audit values or another approved mechanism. + + + +====================================================================== + +25. DEFINITION OF DONE FOR VERSION 1 + +====================================================================== + + + +Version 1 is complete when: + + + +- Both PowerShell scripts are implemented. + +- JSON Schema exists and is documented. + +- Configuration validation includes syntax, schema, semantic, and safety layers. + +- Ordered first-match rule evaluation works. + +- Nested All/Any works within configured depth. + +- Initial property and membership operators are tested. + +- Null behavior matches the approved decision. + +- Required group lookup failures generate EvaluationError. + +- Existing persona is preserved for EvaluationError. + +- Unclassified users are reported distinctly. + +- Each user result is displayed immediately. + +- Interim and final summaries work, including interval 0. + +- Reconciliation checks pass. + +- Logs include UPN and Account Object ID. + +- WhatIf produces zero Graph writes. + +- Changed valid values are the only values written in enforcement mode. + +- The write payload contains only the approved target attribute. + +- Local offline Pester tests pass. + +- Read-only production-tenant tests pass. + +- Azure Automation PowerShell 7 execution passes. + +- Azure DevOps validation/test pipeline passes. + +- Security review confirms permissions and compensating controls. + +- Operational documentation, kill switch, and rollback procedure are complete. + +- WhatIf impact evidence is reviewed before enabling enforcement. + + + +====================================================================== + +26. DEVELOPER STARTING CHECKLIST + +====================================================================== + + + +1. Initialize the Spec Kit project/repository structure. + +2. Convert this baseline into specs/001-persona-engine/spec.md. + +3. Create a requirements traceability list using FR/NFR identifiers. + +4. Complete OTD-001 through OTD-005 before persistence implementation. + +5. Create persona-engine.schema.json. + +6. Create persona-engine.example.json using placeholders only. + +7. Define normalized PowerShell object contracts. + +8. Build the pure rule engine first. + +9. Build offline Pester tests before Graph integration. + +10. Implement configuration validation and noninteractive pipeline mode. + +11. Implement Graph read adapters. + +12. Implement console and structured logging. + +13. Implement the persistence adapter last. + +14. Add ShouldProcess and prove zero writes under WhatIf. + +15. Perform a single-user WhatIf test. + +16. Perform a full-tenant read-only/WhatIf test. + +17. Review summaries, Unclassified results, and EvaluationError results. + +18. Complete permission/security review. + +19. Conduct controlled write testing only after approval. + +20. Document operational handoff. + + + +====================================================================== + +27. SANITIZATION REQUIREMENTS FOR ALL PROJECT ARTIFACTS + +====================================================================== + + + +Reusable examples, documentation, test files, and developer handoff artifacts must not contain: + + + +- Organization/company name + +- Real domain names + +- Real tenant IDs + +- Real subscription IDs + +- Real automation account names + +- Real user UPNs + +- Real user Object IDs + +- Real group names or Object IDs + +- Real role-assignment identifiers + +- Real extension attribute names if considered environment-specific + +- Real Log Analytics workspace details + +- Secrets, tokens, certificates, or credentials + + + +Use placeholders: + + + +- + +- + +- + +- + +- + +- + +- + +- + + + +Synthetic data must be obviously fictional and must not reproduce real employee records. + + + +====================================================================== + +28. FINAL PROJECT BASELINE + +====================================================================== + + + +The Persona Engine will be a modular, configuration-driven PowerShell 7 identity classification service. Version 1 will process Entra user objects, determine exactly one persona through ordered first-match business rules, record Unclassified when no rule matches, preserve the current value when reliable evaluation is impossible, and update only a configured persona attribute when the calculated value changes. + + + +Native PowerShell -WhatIf is the approved no-write control. The production automation identity will be a managed identity. Initial connected development will use read-only permissions, while the pure rule engine and configuration validation will be testable offline with synthetic data. + + + +The project includes two scripts: + + + +1. Invoke-PersonaEngine.ps1 for retrieval, evaluation, reporting, and controlled persistence. + +2. Edit-PersonaEngineConfig.ps1 for validation, interactive editing, synthetic rule testing, and pipeline enforcement. + + + +All outputs will be operational, explainable, and audit-friendly. UPN and Account Object ID are required correlation fields. The exact Entra attribute implementation and attribute-level authorization boundary remain mandatory technical validation items before production write capability is approved. + + + +END OF DOCUMENT