Files
personaEngine2/specs/001-persona-engine/traceability.md
T
2026-08-21 01:18:19 -04:00

9.5 KiB
Raw Blame History

Requirements traceability

Every functional requirement, non-functional requirement, and success criterion in spec.md, mapped to the code that implements it and the test that holds it there.

A row with no test is a requirement nobody is checking. Those are listed explicitly at the bottom rather than left out, because an incomplete matrix that looks complete is worse than no matrix.

Status as at 2026-08-21: 400 offline tests passing; engine purity and sanitization gates passing; no tenant-dependent item verified. The increase from 354 is FR-027FR-030 (rule add/edit/delete in the interactive editor), added to spec.md and implemented in the same change (T122T129).

Functional requirements

ID Requirement Implementation Test
FR-001 Load JSON configuration Import-PersonaConfiguration LayerOrdering.Tests.ps1
FR-002 Validate before connecting Test-PersonaConfiguration; entry script exits 1 before Connect- LayerOrdering.Tests.ps1, ExitCodes.Tests.ps1
FR-003 Adapter-isolated authentication Connect-PersonaGraphInteractive Purity gate; ShouldProcessGate.Tests.ps1
FR-004 Enumerate all users with pagination Get-PersonaUsers Pagination.Tests.ps1
FR-005 Select only required properties Get-PersonaRequiredProperties Pagination.Tests.ps1
FR-006 Retrieve and cache related data Get-PersonaGroupMembership, Get-PersonaCachedMembership Pagination.Tests.ps1, OutcomeExclusivity.Tests.ps1
FR-007 Normalize before evaluation ConvertTo-PersonaUserRecord, ConvertTo-PersonaMembershipRecord RecordContracts.Tests.ps1
FR-008 Evaluate rules in priority order Resolve-UserPersona Ordering.Tests.ps1
FR-009 Stop at first match Resolve-UserPersona Ordering.Tests.ps1
FR-010 Unclassified when nothing matches Resolve-UserPersona Unclassified.Tests.ps1
FR-011 Disabled accounts stay in scope New-PersonaUserRecord exposes AccountEnabled Operators.Tests.ps1
FR-012 Null treated as empty Test-PersonaCondition Operators.Tests.ps1
FR-013 Unretrievable group data yields EvaluationError Tri-state evaluation; facet retrieval flags UnknownNotFalse.Tests.ps1, UnknownPropagation.Tests.ps1
FR-014 Preserve stored value on failure Compare-PersonaValue sets Skipped first EvaluationError.Tests.ps1, WriteGate.Tests.ps1
FR-015 Compare stored and calculated Compare-PersonaValue, ordinal WriteGate.Tests.ps1
FR-016 Write only changed values, four conditions Compare-PersonaValue + run-loop gate WriteGate.Tests.ps1
FR-017 Preview issues no write request Invoke-PersonaEngineRun gate WhatIfZeroWrites.Tests.ps1
FR-018 Immediate per-user output Write-UserPersonaResult Exercised by every run-loop suite
FR-019 Periodic summary Write-PersonaSummary, interval check SummaryInterval.Tests.ps1
FR-020 Interval semantics, final always shown Invoke-PersonaEngineRun SummaryInterval.Tests.ps1
FR-021 Reconciliation at every summary Test-PersonaReconciliation Reconciliation.Tests.ps1
FR-022 Structured audit records New-PersonaAuditRecord, Write-PersonaAuditRecord AuditRecordShape.Tests.ps1
FR-023 Configuration editor Edit-PersonaEngineConfig.ps1 ExitCodes.Tests.ps1 (editor)
FR-024 Non-interactive validation with exit codes -NonInteractive short-circuit NonInteractive.Tests.ps1
FR-025 Synthetic rule testing, no tenant Invoke-SyntheticRuleTest NonInteractive.Tests.ps1
FR-026 Validate and back up before save Save-PersonaConfiguration Safety.Tests.ps1 (PE-SAF-007)
FR-027 Add a rule interactively Add-PersonaConfigRule; [A] command in Edit-PersonaEngineConfig.ps1 EditorAddRule.Tests.ps1, EditorStructuralEdits.Tests.ps1
FR-028 Edit a rule interactively, including its condition tree Get/Add/Remove-PersonaConditionNode, Set-PersonaConditionLeaf; [E] command EditorEditRule.Tests.ps1, EditorStructuralEdits.Tests.ps1
FR-029 Delete a rule interactively, with confirmation Remove-PersonaConfigRule; [D] command EditorDeleteRule.Tests.ps1, EditorStructuralEdits.Tests.ps1
FR-030 Structural edits validated like a hand-edited file Test-PersonaCandidateEdit in Edit-PersonaEngineConfig.ps1 EditorStructuralEdits.Tests.ps1

Rule engine requirements

ID Requirement Implementation Test
RE-001 Required rule fields Schema definitions/rule LayerOrdering.Tests.ps1
RE-002 Unique priorities, lower first Resolve-UserPersona; PE-SEM-002 Ordering.Tests.ps1, Semantic.Tests.ps1
RE-003 all / any with nesting Test-PersonaConditionGroup Composition.Tests.ps1
RE-004 Depth limit and hard ceiling Test-PersonaConditionGroup; PE-SEM-012, PE-SEM-013 Composition.Tests.ps1, Semantic.Tests.ps1
RE-005 Thirteen operators Test-PersonaCondition Operators.Tests.ps1
RE-006 Case-insensitive; regex validated first Test-PersonaCondition; PE-SEM-016 Operators.Tests.ps1, Semantic.Tests.ps1
RE-007 Per-condition membership mode Three-facet MembershipRecord RecordContracts.Tests.ps1, UnknownPropagation.Tests.ps1
RE-008 Combined identity sources Get-PersonaRequiredFacets OutcomeExclusivity.Tests.ps1
RE-009 Special accounts by Object ID Example configuration; no hard-coded path Purity gate

Validation requirements

ID Requirement Implementation Test
VR-001 Four ordered layers, fail-fast Test-PersonaConfiguration LayerOrdering.Tests.ps1
VR-002 Sixteen semantic conditions Test-PersonaConfigurationSemantic Semantic.Tests.ps1 — one test per code
VR-003 Seven safety conditions Test-PersonaConfigurationSafety Safety.Tests.ps1, TraceAcknowledgement.Tests.ps1
VR-004 Finding shape New-PersonaValidationFinding Semantic.Tests.ps1, Safety.Tests.ps1, RecordContracts.Tests.ps1
VR-005 Warnings block only on request Editor exit-code mapping ExitCodes.Tests.ps1 (editor)

Non-functional requirements

ID Requirement Implementation Test
NFR-001 PowerShell 7 #Requires -Version 7.2; manifest floor Runs on 7.6.5
NFR-002 Caching, per-user and total duration New-PersonaDataCache; stopwatch in Resolve-UserPersona; RunComplete.durationMs AuditCompleteness.Tests.ps1no target set
NFR-003 Pagination, bounded retry, backoff Invoke-PersonaGraphRequest RetryPolicy.Tests.ps1, Pagination.Tests.ps1
NFR-004 Comment-based help on public functions Every function in src/ Manual review
NFR-005 Run ID, UPN, Object ID, config hash New-PersonaAuditContext AuditCompleteness.Tests.ps1
NFR-006 Least privilege, single attribute, no secrets Six OTD-003 controls WriteBody.Tests.ps1, WriteBodyRejection.Tests.ps1, sanitization gate
NFR-007 Engine and validation run without the platform Purity; layer dot-sourcing Purity gate; whole offline suite
NFR-008 No Windows PowerShell-only dependencies Microsoft.Graph.Authentication only Unverified in Automation (V-5b)

Success criteria

ID Criterion Test Status
SC-001 Exactly one outcome per user OutcomeExclusivity.Tests.ps1 Passing
SC-002 Second run proposes zero changes Idempotence.Tests.ps1 Passing
SC-003 Determinism across shuffled input Determinism.Tests.ps1 Passing
SC-004 Zero writes under -WhatIf WhatIfZeroWrites.Tests.ps1 Passing
SC-005 Single-attribute request body WriteBody.Tests.ps1 Passing
SC-006 Audit completeness AuditCompleteness.Tests.ps1 Passing
SC-007 Reconciliation, and its failure path Reconciliation.Tests.ps1 Passing
SC-008 Everything runs offline Whole offline suite; validate.yml gate 7 Passing
SC-009 Every VR-002 and VR-003 condition detected Semantic.Tests.ps1, Safety.Tests.ps1 Passing
SC-010 Non-interactive never prompts or hangs NonInteractive.Tests.ps1 Passing
SC-011 Every exit code reachable ExitCodes.Tests.ps1 (both) Passing
SC-012 Per-user output is immediate Write-UserPersonaResult emits in process Structural, not timed
SC-013 No tenant data committed Test-Sanitization.ps1 Passing

Gaps, stated plainly

Item Why it is not covered What would close it
NFR-002 performance No target exists until representative tenant testing A timed run against a real population
NFR-004 help coverage Reviewed by eye, not asserted A test parsing every exported function for a help block
NFR-008 Automation compatibility No Automation account available V-5b (T116)
SC-012 timing Asserted structurally, not measured A timed harness — low value against the cost
V-1, V-2, V-3 Require a tenant Stage A2 and A3 runs
V-4 Requires a person Written security sign-off
Phase 13 (T115T121) Requires an Automation account Stage B

How to keep this honest

When a requirement's implementation moves, this table moves with it. When a test is deleted, the row it backed becomes a gap and belongs in the gaps table, not silently in the main one. A matrix that is allowed to drift is worse than none, because it converts "we do not know" into "we checked".