From db6ad1f3e8b04f7cda10222421f4021ad8f35cb4 Mon Sep 17 00:00:00 2001 From: Dave Date: Thu, 20 Aug 2026 16:48:44 -0400 Subject: [PATCH] add constitution --- .specify/memory/constitution.md | 195 ++++++++++++++++++++++++++------ 1 file changed, 160 insertions(+), 35 deletions(-) diff --git a/.specify/memory/constitution.md b/.specify/memory/constitution.md index a4670ff..31604f0 100644 --- a/.specify/memory/constitution.md +++ b/.specify/memory/constitution.md @@ -1,50 +1,175 @@ -# [PROJECT_NAME] Constitution - + + +# Persona Engine Constitution ## Core Principles -### [PRINCIPLE_1_NAME] - -[PRINCIPLE_1_DESCRIPTION] - +### I. Deterministic, Single-Persona Classification (NON-NEGOTIABLE) -### [PRINCIPLE_2_NAME] - -[PRINCIPLE_2_DESCRIPTION] - +Identical input records and identical configuration MUST always produce an identical persona +decision. Every evaluated account MUST receive exactly one persona — never zero, never +several. Rules MUST be evaluated in ascending numeric priority order and evaluation MUST stop +at the first match. When all enabled rules evaluate successfully and none match, the result +MUST be `Unclassified`; when evaluation cannot complete reliably, the result MUST be +`EvaluationError`. Non-deterministic inputs — wall-clock time, random values, unordered +collection enumeration, or environment state — MUST NOT influence a decision. -### [PRINCIPLE_3_NAME] - -[PRINCIPLE_3_DESCRIPTION] - +**Rationale**: Persona values drive access and Conditional Access decisions. A classification +that varies between runs is unreviewable and cannot be safely enforced. -### [PRINCIPLE_4_NAME] - -[PRINCIPLE_4_DESCRIPTION] - +### II. Configuration-Driven Rules -### [PRINCIPLE_5_NAME] - -[PRINCIPLE_5_DESCRIPTION] - +Business classification logic MUST live in JSON configuration, never in PowerShell source. The +engine implements condition operators and composition (`all` / `any` nesting within the +configured depth limit); it MUST NOT hard-code personas, priorities, group identifiers, role +identifiers, or tenant-specific attribute names. The candidate persona catalogue is business +data, not engine behaviour. JSON is the only supported configuration format for v1. +Configuration MUST be validated in four layers — JSON syntax, JSON Schema, semantic, then +safety — before it is used to evaluate any account. -## [SECTION_2_NAME] - +**Rationale**: Rule changes are business changes. Requiring a code change to reclassify accounts +couples routine policy updates to the release pipeline and invites unreviewed edits. -[SECTION_2_CONTENT] - +### III. Fail-Safe, Idempotent Persistence (NON-NEGOTIABLE) -## [SECTION_3_NAME] - +Re-running the engine MUST change nothing unless a calculated value actually differs from the +stored value. A missing or failed required data source MUST NOT be interpreted as a non-match: +the account MUST be recorded as `EvaluationError`, its existing persona MUST be preserved, no +write MUST be attempted for it, and the run MUST continue. Write-capable entry points MUST use +`CmdletBinding` with `SupportsShouldProcess`, and `-WhatIf` MUST produce zero directory writes. +`-Debug` and `-Verbose` MUST NOT be treated as read-only controls. A write payload MUST contain +only the single approved target attribute. -[SECTION_3_CONTENT] - +**Rationale**: The engine writes to a live directory. Silent misclassification of a privileged +account is a security incident, so unavailable data must degrade to no change. + +### IV. Pure Rule Engine, Tested Offline First + +The rule engine MUST NOT depend on Microsoft Graph, authentication, Azure Automation, or console +rendering. Graph acquisition MUST be normalized into plain identity records before evaluation, +and persistence MUST sit behind an adapter the engine does not call directly. The rule engine +MUST be implemented and passing Pester tests against synthetic data before any Graph integration +is written, and the persistence adapter MUST be implemented last. Offline unit tests MUST run to +completion with no tenant connectivity and no credentials. + +**Rationale**: Correctness of classification is provable only in isolation. A rule engine +reachable only through a live tenant cannot be exhaustively tested before it is trusted. + +### V. Explainable, Sanitized Observability + +Every persona result MUST identify the matched rule ID (or `Unclassified` / `EvaluationError`), +the run correlation ID, the UPN, and the Account Object ID. Each user result MUST be emitted +immediately as it is produced, with interim and final summaries, and reconciliation MUST confirm +that reported counts match accounts processed. Structured, audit-friendly logging is required +alongside console output. UPN and Account Object ID are approved for logs. Access tokens, +authorization headers, secrets, and full Graph responses MUST NEVER be logged. Detailed +condition-level values are diagnostic-only and MUST be gated behind `-Debug`. + +**Rationale**: An unexplainable decision cannot be reviewed, appealed, or audited, and the +`-WhatIf` impact evidence required before enforcement depends on complete per-user output. + +## Security and Least-Privilege Constraints + +- **Authentication**: Azure Automation MUST use a managed identity. Local development MUST use an + approved interactive or read-only application identity. Client secrets MUST NEVER be committed + to source control. +- **Least privilege**: The execution identity MUST be granted only what the enabled rules require + — in-scope user properties, configured group membership, configured role data, and the existing + persona value. +- **Attribute-scoped writes**: Whether Entra can enforce write authorization at the individual + attribute level MUST be verified, never assumed (OTD-003). Until verified, the compensating + controls are mandatory: the persistence module accepts only the approved target attribute; that + attribute MUST appear in `approvedWritableAttributes`; validation rejects all others; a + dedicated function builds a request body containing only that attribute; tests inspect the + request body; and code owners gate persistence changes. +- **Sanitization**: Every artifact in this repository — docs, examples, tests, configuration + samples, specs — MUST be free of organization names, real domains, tenant or subscription IDs, + automation account names, real UPNs or Object IDs, real group or role identifiers, + environment-specific attribute names, log destination details, and any secret, token, + certificate, or credential. Only approved placeholders such as ``, + ``, ``, ``, and + `` may be used. Test data MUST be obviously fictional and MUST + NEVER reproduce real employee records. Tenant-specific configuration belongs in a protected + repository or configuration store, not here. +- **Scope**: v1 covers Entra user objects only. Service principals, managed identities, workload + identities, and agentic identities are out of scope, and the architecture MUST NOT assume they + share user-object properties. +- **Kill switch and rollback**: A documented kill switch (disable the Automation schedule, run + with `-WhatIf`, revoke production write permission, or disable write deployment stages) and a + documented rollback procedure MUST exist before enforcement is enabled. +- **Runtime**: PowerShell 7 is the target runtime for both local execution and Azure Automation. + +## Development Workflow and Quality Gates + +- **Spec-driven delivery**: Nothing is implemented before it is specified, planned, and decomposed + into tasks (Specify → Plan → Tasks → Implement). Any unresolved question MUST be captured as an + explicit assumption, risk, or architecture decision — it MUST NEVER be silently implemented. +- **Open technical decisions**: OTD-001 through OTD-005 MUST be closed in `research.md` or an ADR + before any persistence implementation begins. +- **Build order**: Pure rule engine with offline Pester tests → configuration validation and + non-interactive pipeline mode → Graph read adapters → console and structured logging → + persistence adapter last, with tests proving zero writes under `-WhatIf`. +- **Traceability**: Requirements carry FR/NFR identifiers and MUST be traceable from spec through + tasks to tests. +- **Validation pipeline** (MUST pass before merge): repository hygiene and sanitization checks, + PowerShell static analysis, JSON Schema validation, semantic and safety configuration + validation, Pester unit tests, Pester safety tests, test result publication, and artifact + packaging. +- **Release pipeline**: validate the approved branch or tag, repeat validation and tests, package, + deploy to Azure Automation, import modules, publish the runbook with the schedule **disabled**, + execute `-WhatIf` validation, pass an approval gate, then enable enforcement. +- **Mandatory review**: Changes to the target attribute, `approvedWritableAttributes`, rule + priority, rule enablement, rule conditions, persona outputs, authentication permissions, + persistence functions, logging destination, or `WhatIf` / `ShouldProcess` behaviour MUST be + reviewed by a code owner. Delivery uses feature branches, pull requests, and a protected release + branch. +- **Definition of done**: A version is complete only when its `-WhatIf` impact evidence has been + reviewed and security review has confirmed permissions and compensating controls. ## Governance - -[GOVERNANCE_RULES] - +This constitution supersedes all other development practices for this repository. Where a plan, +task list, or review comment conflicts with it, this document wins. -**Version**: [CONSTITUTION_VERSION] | **Ratified**: [RATIFICATION_DATE] | **Last Amended**: [LAST_AMENDED_DATE] - +**Amendment procedure**: Amendments MUST be proposed as a change to this file in a pull request, +MUST state the rationale and the version bump type, and MUST be approved by a code owner. An +amendment that invalidates existing artifacts MUST include a migration note naming the specs, +plans, tasks, or code that require updating. + +**Versioning policy**: This constitution uses semantic versioning. + +- **MAJOR** — a principle or governance rule is removed or redefined in a backward-incompatible way. +- **MINOR** — a new principle or section is added, or existing guidance is materially expanded. +- **PATCH** — clarifications, wording, and typo fixes with no change in obligation. + +**Compliance review**: Every pull request MUST verify compliance with these principles, and +reviewers MUST reject changes that violate a NON-NEGOTIABLE principle regardless of urgency. +Complexity that departs from these principles MUST be justified in writing in the plan's +complexity tracking, or the simpler compliant approach MUST be taken instead. `README.md` and the +feature's `spec.md`, `plan.md`, and `tasks.md` provide runtime development guidance and MUST be +kept consistent with this constitution. + +**Version**: 1.0.0 | **Ratified**: 2026-08-20 | **Last Amended**: 2026-08-20