config editor
This commit is contained in:
@@ -73,6 +73,29 @@ Stability matters: pipelines and runbooks will match on these codes.
|
||||
| `3` | Configuration file not found or unreadable |
|
||||
| `4` | Schema file not found or itself invalid |
|
||||
|
||||
## Interactive editor commands (FR-023, FR-027 – FR-030)
|
||||
|
||||
The interactive loop (entered when neither `-ValidateOnly` nor `-NonInteractive` is set) supports:
|
||||
|
||||
| Command | Behaviour |
|
||||
| --- | --- |
|
||||
| List rules | Show every rule's priority, ID, persona, and enabled state. |
|
||||
| Toggle a rule | Flip `enabled` on an existing rule. |
|
||||
| Change a priority | Set a new numeric priority on an existing rule. |
|
||||
| **Add a rule** | Prompt for every RE-001 field (`id`, `name`, `description`, `priority`, `persona`, `enabled`, and optional fields) and for the condition tree — nested `all`/`any` groups and, per leaf condition, the property/membership source, operator, and comparison value. Reject on the spot if the `id` or `priority` collides with an existing rule (FR-027). |
|
||||
| **Edit a rule** | Select an existing rule by `id`; change any top-level field and/or the condition tree — add, edit, remove, or renest conditions and groups within `MaxConditionDepth` (FR-028). |
|
||||
| **Delete a rule** | Select an existing rule by `id`; show its `id`, `name`, and `priority` and require explicit confirmation before removing it (FR-029). |
|
||||
| Re-validate | Run all four validation layers against the in-memory document, including any unsaved add/edit/delete, and print findings without saving. |
|
||||
| Run rule test | Evaluate the in-memory document (including unsaved structural edits) against `-TestDataPath` fixtures. |
|
||||
| Save | Re-validate, then persist per the save contract below. |
|
||||
| Quit | Warn if there are unsaved changes (including structural edits) before discarding them. |
|
||||
|
||||
All structural edits (add/edit/delete) are applied to the in-memory document only. They are never
|
||||
written to `-ConfigPath` (or `-OutputPath`) until a `Save` re-validates the full document and that
|
||||
validation passes — the same rule that governs field-level edits (FR-030). A depth violation
|
||||
introduced by an add or edit is reported immediately using the same finding the runtime validator
|
||||
would produce, rather than deferred to the next save or re-validate.
|
||||
|
||||
## Save contract (FR-026)
|
||||
|
||||
1. Re-validate the edited document in full.
|
||||
|
||||
@@ -84,7 +84,7 @@ An operator watching a run sees each user's result appear immediately, receives
|
||||
|
||||
### User Story 5 - Validate and edit configuration safely (Priority: P2)
|
||||
|
||||
A configuration owner validates a configuration file, edits rules interactively, tests rules against synthetic sample users, compares against another configuration, and saves only after validation passes — with a backup taken first.
|
||||
A configuration owner validates a configuration file, adds, edits, and deletes rules interactively — including each rule's condition tree — tests rules against synthetic sample users, compares against another configuration, and saves only after validation passes — with a backup taken first.
|
||||
|
||||
**Why this priority**: Makes the configuration-driven model usable and safe in practice, but the engine can be exercised with a hand-authored file first.
|
||||
|
||||
@@ -96,6 +96,13 @@ A configuration owner validates a configuration file, edits rules interactively,
|
||||
2. **Given** an edit session with unsaved valid changes, **When** the file is saved over an existing configuration, **Then** a timestamped backup or save-as output is produced first.
|
||||
3. **Given** synthetic sample users are supplied, **When** rules are tested, **Then** the resulting persona for each sample is reported without any tenant connection.
|
||||
4. **Given** a valid configuration, **When** validation runs, **Then** no Error findings are produced and the file is accepted.
|
||||
5. **Given** an interactive edit session, **When** the configuration owner adds a new rule, **Then** they are prompted for every required field (`id`, `name`, `description`, `priority`, `persona`, `enabled`) and for the rule's condition tree — including nested `all`/`any` groups and, for each leaf condition, the property or membership source, operator, and comparison value — and the new rule is appended to the in-memory document without being written to disk until save.
|
||||
6. **Given** an interactive edit session, **When** the configuration owner attempts to add a rule using an `id` or `priority` already present in the document, **Then** the attempt is rejected before the rule is added, with a message naming the conflicting rule.
|
||||
7. **Given** an interactive edit session, **When** the configuration owner selects an existing rule to edit, **Then** they can change any of its top-level fields and its condition tree — adding, editing, removing, or renesting conditions and `all`/`any` groups within the configured depth limit — and the change is held in memory, unsaved, until the session validates and saves.
|
||||
8. **Given** an interactive edit session, **When** the configuration owner deletes a rule, **Then** they are shown the rule's `id`, `name`, and `priority` and asked to confirm before it is removed from the in-memory document.
|
||||
9. **Given** a rule add, edit, or delete has been made in an edit session, **When** the session re-validates or saves, **Then** the same four validation layers (VR-001) run over the modified document exactly as they would over a hand-edited file, and any resulting Error finding blocks the save.
|
||||
10. **Given** an edit session with unsaved add, edit, or delete changes, **When** the operator quits without saving, **Then** they are warned that unsaved changes will be lost and the file on disk is unchanged.
|
||||
11. **Given** a rule add, edit, or delete would exceed the configured maximum condition nesting depth, **When** the change is applied, **Then** it is rejected at edit time with the same finding the runtime validator would produce, rather than deferred to the next save.
|
||||
|
||||
---
|
||||
|
||||
@@ -219,6 +226,10 @@ Requirement identifiers are carried forward unchanged from the Phase 0 baseline
|
||||
- **FR-024** — Non-interactive validation: the configuration tool MUST support non-interactive validation and return a non-zero exit code on failure.
|
||||
- **FR-025** — Configuration test data: the editor MUST support testing rules against synthetic sample users without tenant connectivity.
|
||||
- **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.
|
||||
- **FR-027** — Add a rule: the interactive editor MUST support adding a new rule, prompting for every field in RE-001 and for the rule's condition tree (nested `all`/`any` groups and leaf conditions), and MUST reject an `id` or `priority` that collides with an existing rule before the rule is added.
|
||||
- **FR-028** — Edit a rule: the interactive editor MUST support editing any field of an existing rule, including full editing of its condition tree — adding, changing, removing, and renesting conditions and groups within the configured depth limit (RE-004).
|
||||
- **FR-029** — Delete a rule: the interactive editor MUST support deleting an existing rule, and MUST require the operator to confirm against the rule's `id`, `name`, and `priority` before removal.
|
||||
- **FR-030** — Uniform validation for structural edits: a rule added, edited, or deleted in the interactive editor MUST be subject to the same four validation layers (VR-001) as a hand-edited file, at re-validation and at save; edits are held only in memory until save succeeds (FR-026).
|
||||
|
||||
### Rule Engine Requirements
|
||||
|
||||
|
||||
@@ -28,16 +28,21 @@ pass offline Pester tests before any Graph integration exists.
|
||||
Single PowerShell module at repository root: `src/`, `tests/`, `config/`, `docs/`, `pipelines/`,
|
||||
per the Project Structure section of [plan.md](plan.md).
|
||||
|
||||
## Implementation status — 2026-08-20
|
||||
## Implementation status — 2026-08-21
|
||||
|
||||
**109 of 121 tasks complete.** All twelve remaining tasks require something this workstation does not
|
||||
**117 of 129 tasks complete.** All twelve remaining tasks require something this workstation does not
|
||||
have: a tenant connection (T055, T056, T101–T103) or an Azure Automation account (Phase 13,
|
||||
T115–T121). Nothing offline-implementable is outstanding.
|
||||
|
||||
T122–T129 (interactive add/edit/delete for rules, FR-027–FR-030) landed after the initial Phase 6
|
||||
build, which had shipped with toggle/priority editing only. 400 offline Pester tests now pass (up
|
||||
from 354); see [traceability.md](traceability.md) for FR-027–FR-030's implementation and test
|
||||
mapping.
|
||||
|
||||
```
|
||||
354 offline Pester tests PASS
|
||||
400 offline Pester tests PASS
|
||||
Engine purity (Principle IV) PASS
|
||||
Sanitization (SC-013) PASS 156 files
|
||||
Sanitization (SC-013) PASS
|
||||
Graph module loaded during tests False (SC-008 holds)
|
||||
```
|
||||
|
||||
@@ -235,7 +240,28 @@ documented finding code, severity, and location.
|
||||
- [X] T069 [US5] Implement the timestamped backup and Save-As path in Edit-PersonaEngineConfig.ps1 (FR-026)
|
||||
- [X] T070 [US5] Implement synthetic rule testing via `-TestDataPath` in Edit-PersonaEngineConfig.ps1, reusing the rule engine with no tenant connectivity (FR-025)
|
||||
|
||||
**Checkpoint**: invalid configurations cannot reach the engine or overwrite a good file.
|
||||
### Rule CRUD in the interactive editor (US5 addition — FR-027–FR-030)
|
||||
|
||||
Added after the initial Phase 6 build. The editor originally shipped deliberately scoped to
|
||||
toggle/priority only (see the `Invoke-InteractiveEditor` comment header); spec.md now requires
|
||||
add/edit/delete, including full condition-tree editing, so that scope is reversed here rather than
|
||||
worked around.
|
||||
|
||||
#### Tests for rule CRUD
|
||||
|
||||
- [X] T122 [P] [US5] Add-rule tests in tests/Configuration/EditorAddRule.Tests.ps1 covering the full field/condition-tree prompt sequence and rejection of a duplicate `id` or `priority` before the rule is added (FR-027)
|
||||
- [X] T123 [P] [US5] Edit-rule tests in tests/Configuration/EditorEditRule.Tests.ps1 covering top-level field changes and condition-tree add/edit/remove/renest operations within `MaxConditionDepth` (FR-028)
|
||||
- [X] T124 [P] [US5] Delete-rule tests in tests/Configuration/EditorDeleteRule.Tests.ps1 covering the `id`/`name`/`priority` confirmation prompt and removal, including a declined confirmation leaving the rule in place (FR-029)
|
||||
- [X] T125 [P] [US5] Structural-edit validation tests in tests/Configuration/EditorStructuralEdits.Tests.ps1 asserting add/edit/delete changes stay in memory until save, re-validate through all four layers on `[V]`/`[S]`, and that a depth-limit violation is reported immediately at edit time rather than deferred (FR-030)
|
||||
|
||||
#### Implementation for rule CRUD
|
||||
|
||||
- [X] T126 [US5] Implement rule addition (prompt for every RE-001 field plus the condition tree, reject a colliding `id`/`priority`) in Edit-PersonaEngineConfig.ps1 and wire the `[A]` command into the interactive loop (FR-027)
|
||||
- [X] T127 [US5] Implement rule editing (top-level fields plus add/edit/remove/renest on the condition tree) in Edit-PersonaEngineConfig.ps1 and wire the `[E]` command into the interactive loop (FR-028)
|
||||
- [X] T128 [US5] Implement rule deletion with an `id`/`name`/`priority` confirmation prompt in Edit-PersonaEngineConfig.ps1 and wire the `[D]` command into the interactive loop (FR-029)
|
||||
- [X] T129 [US5] Route add/edit/delete through the existing `$dirty` tracking and `Invoke-ConfigurationValidation` re-validation path in Edit-PersonaEngineConfig.ps1, and surface a depth-limit finding at edit time using the same check the runtime validator uses (FR-030)
|
||||
|
||||
**Checkpoint**: invalid configurations cannot reach the engine or overwrite a good file, and rules can be added, edited, and deleted entirely from the editor.
|
||||
|
||||
---
|
||||
|
||||
@@ -430,7 +456,7 @@ reads the audit shape US7 defines.
|
||||
| 3 | T016–T020 (all tests, separate files) |
|
||||
| 4 | T027, T028, T029 |
|
||||
| 5 | T034–T038 (tests); then T039, T040 |
|
||||
| 6 | T057–T060 |
|
||||
| 6 | T057–T060; then T122–T125 |
|
||||
| 7 | T071, T072 |
|
||||
| 8 | T077, T078 |
|
||||
| 9 | T083, T084, T085 |
|
||||
@@ -470,7 +496,7 @@ Automation PowerShell 7 run.
|
||||
| 3 | US2 (P1) | T016–T026 | 11 |
|
||||
| 4 | US3 (P1) | T027–T033 | 7 |
|
||||
| 5 | US1 (P1) 🎯 | T034–T056 | 23 |
|
||||
| 6 | US5 (P2) | T057–T070 | 14 |
|
||||
| 6 | US5 (P2) | T057–T070, T122–T129 | 22 |
|
||||
| 7 | US6 (P2) | T071–T076 | 6 |
|
||||
| 8 | US4 (P2) | T077–T082 | 6 |
|
||||
| 9 | US7 (P2) | T083–T090 | 8 |
|
||||
@@ -478,4 +504,4 @@ Automation PowerShell 7 run.
|
||||
| 11 | US8 (P3) 🔒 | T095–T103 | 9 |
|
||||
| 12 Polish | — | T104–T114 | 11 |
|
||||
| 13 Stage B | — | T115–T121 | 7 (deferred) |
|
||||
| **Total** | | | **121** |
|
||||
| **Total** | | | **129** |
|
||||
|
||||
@@ -6,8 +6,9 @@ Every functional requirement, non-functional requirement, and success criterion
|
||||
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-20**: 354 offline tests passing; engine purity and sanitization gates passing;
|
||||
no tenant-dependent item verified.
|
||||
**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-027–FR-030 (rule add/edit/delete in
|
||||
the interactive editor), added to spec.md and implemented in the same change (T122–T129).
|
||||
|
||||
## Functional requirements
|
||||
|
||||
@@ -39,6 +40,10 @@ no tenant-dependent item verified.
|
||||
| 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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user