Compare commits
2 Commits
cfdcfcd873
...
c59c85dd55
| Author | SHA1 | Date | |
|---|---|---|---|
| c59c85dd55 | |||
| db6ad1f3e8 |
+160
-35
@@ -1,50 +1,175 @@
|
|||||||
# [PROJECT_NAME] Constitution
|
<!--
|
||||||
<!-- Example: Spec Constitution, TaskFlow Constitution, etc. -->
|
Sync Impact Report
|
||||||
|
==================
|
||||||
|
Version change: (unversioned template) → 1.0.0
|
||||||
|
Bump rationale: Initial ratification. All placeholder tokens replaced with concrete,
|
||||||
|
project-specific governance derived from README.md and the approved
|
||||||
|
Phase 0 baseline (Persona-Engine-Developer-Handoff.txt).
|
||||||
|
|
||||||
|
Modified principles:
|
||||||
|
[PRINCIPLE_1_NAME] → I. Deterministic, Single-Persona Classification (NON-NEGOTIABLE)
|
||||||
|
[PRINCIPLE_2_NAME] → II. Configuration-Driven Rules
|
||||||
|
[PRINCIPLE_3_NAME] → III. Fail-Safe, Idempotent Persistence (NON-NEGOTIABLE)
|
||||||
|
[PRINCIPLE_4_NAME] → IV. Pure Rule Engine, Tested Offline First
|
||||||
|
[PRINCIPLE_5_NAME] → V. Explainable, Sanitized Observability
|
||||||
|
|
||||||
|
Added sections:
|
||||||
|
[SECTION_2_NAME] → Security and Least-Privilege Constraints
|
||||||
|
[SECTION_3_NAME] → Development Workflow and Quality Gates
|
||||||
|
Governance rules populated (amendment procedure, versioning policy, compliance review)
|
||||||
|
|
||||||
|
Removed sections: none
|
||||||
|
|
||||||
|
Follow-up TODOs: none — no placeholders deferred.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# Persona Engine Constitution
|
||||||
|
|
||||||
## Core Principles
|
## Core Principles
|
||||||
|
|
||||||
### [PRINCIPLE_1_NAME]
|
### I. Deterministic, Single-Persona Classification (NON-NEGOTIABLE)
|
||||||
<!-- Example: I. Library-First -->
|
|
||||||
[PRINCIPLE_1_DESCRIPTION]
|
|
||||||
<!-- Example: Every feature starts as a standalone library; Libraries must be self-contained, independently testable, documented; Clear purpose required - no organizational-only libraries -->
|
|
||||||
|
|
||||||
### [PRINCIPLE_2_NAME]
|
Identical input records and identical configuration MUST always produce an identical persona
|
||||||
<!-- Example: II. CLI Interface -->
|
decision. Every evaluated account MUST receive exactly one persona — never zero, never
|
||||||
[PRINCIPLE_2_DESCRIPTION]
|
several. Rules MUST be evaluated in ascending numeric priority order and evaluation MUST stop
|
||||||
<!-- Example: Every library exposes functionality via CLI; Text in/out protocol: stdin/args → stdout, errors → stderr; Support JSON + human-readable formats -->
|
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]
|
**Rationale**: Persona values drive access and Conditional Access decisions. A classification
|
||||||
<!-- Example: III. Test-First (NON-NEGOTIABLE) -->
|
that varies between runs is unreviewable and cannot be safely enforced.
|
||||||
[PRINCIPLE_3_DESCRIPTION]
|
|
||||||
<!-- Example: TDD mandatory: Tests written → User approved → Tests fail → Then implement; Red-Green-Refactor cycle strictly enforced -->
|
|
||||||
|
|
||||||
### [PRINCIPLE_4_NAME]
|
### II. Configuration-Driven Rules
|
||||||
<!-- Example: IV. Integration Testing -->
|
|
||||||
[PRINCIPLE_4_DESCRIPTION]
|
|
||||||
<!-- Example: Focus areas requiring integration tests: New library contract tests, Contract changes, Inter-service communication, Shared schemas -->
|
|
||||||
|
|
||||||
### [PRINCIPLE_5_NAME]
|
Business classification logic MUST live in JSON configuration, never in PowerShell source. The
|
||||||
<!-- Example: V. Observability, VI. Versioning & Breaking Changes, VII. Simplicity -->
|
engine implements condition operators and composition (`all` / `any` nesting within the
|
||||||
[PRINCIPLE_5_DESCRIPTION]
|
configured depth limit); it MUST NOT hard-code personas, priorities, group identifiers, role
|
||||||
<!-- Example: Text I/O ensures debuggability; Structured logging required; Or: MAJOR.MINOR.BUILD format; Or: Start simple, YAGNI principles -->
|
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
|
||||||
<!-- Example: Additional Constraints, Security Requirements, Performance Standards, etc. -->
|
couples routine policy updates to the release pipeline and invites unreviewed edits.
|
||||||
|
|
||||||
[SECTION_2_CONTENT]
|
### III. Fail-Safe, Idempotent Persistence (NON-NEGOTIABLE)
|
||||||
<!-- Example: Technology stack requirements, compliance standards, deployment policies, etc. -->
|
|
||||||
|
|
||||||
## [SECTION_3_NAME]
|
Re-running the engine MUST change nothing unless a calculated value actually differs from the
|
||||||
<!-- Example: Development Workflow, Review Process, Quality Gates, etc. -->
|
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
|
||||||
<!-- Example: Code review requirements, testing gates, deployment approval process, etc. -->
|
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 `<ORGANIZATION-NAME>`,
|
||||||
|
`<TENANT-ID>`, `<ACCOUNT-OBJECT-ID>`, `<GROUP-OBJECT-ID>`, and
|
||||||
|
`<APPROVED-PERSONA-ATTRIBUTE-NAME>` 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
|
||||||
<!-- Example: Constitution supersedes all other practices; Amendments require documentation, approval, migration plan -->
|
|
||||||
|
|
||||||
[GOVERNANCE_RULES]
|
This constitution supersedes all other development practices for this repository. Where a plan,
|
||||||
<!-- Example: All PRs/reviews must verify compliance; Complexity must be justified; Use [GUIDANCE_FILE] for runtime development guidance -->
|
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,
|
||||||
<!-- Example: Version: 2.1.1 | Ratified: 2025-06-13 | Last Amended: 2025-07-16 -->
|
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
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ A modular, configuration-driven **PowerShell 7** identity-classification service
|
|||||||
|
|
||||||
The engine enumerates Entra user accounts, evaluates each one against an ordered, JSON-defined rule set, deterministically assigns **exactly one persona**, and updates a single approved persona attribute — and only when the calculated value differs from the current value.
|
The engine enumerates Entra user accounts, evaluates each one against an ordered, JSON-defined rule set, deterministically assigns **exactly one persona**, and updates a single approved persona attribute — and only when the calculated value differs from the current value.
|
||||||
|
|
||||||
> **Project status: Phase 0 — approved requirements baseline.**
|
> **Project status: Phase 1 complete — specification drafted.**
|
||||||
> No implementation code exists yet. The authoritative baseline is
|
> No implementation code exists yet. The approved requirements baseline is
|
||||||
> [`Persona-Engine-Developer-Handoff.txt`](Persona-Engine-Developer-Handoff.txt).
|
> [`Persona-Engine-Developer-Handoff.txt`](Persona-Engine-Developer-Handoff.txt), now converted
|
||||||
> The next step is Phase 1: convert that baseline into `specs/001-persona-engine/spec.md`.
|
> into [`specs/001-persona-engine/spec.md`](specs/001-persona-engine/spec.md). Project governance
|
||||||
|
> is ratified in [`.specify/memory/constitution.md`](.specify/memory/constitution.md) (v1.0.0).
|
||||||
|
> The next step is Phase 2: produce `plan.md` and `research.md`, closing OTD-001 through OTD-005.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -22,8 +24,9 @@ Specify -> Plan -> Tasks -> Implement
|
|||||||
| Stage | Artifact | Phase | State |
|
| Stage | Artifact | Phase | State |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| Baseline | `Persona-Engine-Developer-Handoff.txt` | 0 | Approved |
|
| Baseline | `Persona-Engine-Developer-Handoff.txt` | 0 | Approved |
|
||||||
| Specify | `specs/001-persona-engine/spec.md` | 1 | Not started |
|
| Constitution | `.specify/memory/constitution.md` | 0 | Ratified v1.0.0 |
|
||||||
| Plan | `specs/001-persona-engine/plan.md`, `research.md` | 2 | Not started |
|
| Specify | `specs/001-persona-engine/spec.md` | 1 | Draft complete |
|
||||||
|
| Plan | `specs/001-persona-engine/plan.md`, `research.md` | 2 | In progress |
|
||||||
| Contracts | `data-model.md`, `contracts/`, `persona-engine.schema.json` | 3 | Not started |
|
| Contracts | `data-model.md`, `contracts/`, `persona-engine.schema.json` | 3 | Not started |
|
||||||
| Tasks | `specs/001-persona-engine/tasks.md` | 4 | Not started |
|
| Tasks | `specs/001-persona-engine/tasks.md` | 4 | Not started |
|
||||||
| Implement | `src/`, `tests/`, `pipelines/` | 5–12 | Not started |
|
| Implement | `src/`, `tests/`, `pipelines/` | 5–12 | Not started |
|
||||||
@@ -245,10 +248,10 @@ Research items to be resolved in `research.md` or an ADR. **OTD-001 through OTD-
|
|||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
Implementation has not begun. The current work item is Phase 1.
|
Implementation has not begun. The current work item is Phase 2 — planning.
|
||||||
|
|
||||||
1. Initialize the Spec Kit project structure.
|
1. ~~Initialize the Spec Kit project structure.~~ Done.
|
||||||
2. Convert the handoff baseline into `specs/001-persona-engine/spec.md`.
|
2. ~~Convert the handoff baseline into `specs/001-persona-engine/spec.md`.~~ Done.
|
||||||
3. Build a requirements traceability list using FR/NFR identifiers.
|
3. Build a requirements traceability list using FR/NFR identifiers.
|
||||||
4. Close OTD-001 through OTD-005 before any persistence work.
|
4. Close OTD-001 through OTD-005 before any persistence work.
|
||||||
5. Create `persona-engine.schema.json` and a placeholder-only `persona-engine.example.json`.
|
5. Create `persona-engine.schema.json` and a placeholder-only `persona-engine.example.json`.
|
||||||
|
|||||||
Reference in New Issue
Block a user