Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions Docs/Decision/Adr/ADR_019_Governance_Package_Separation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# ADR-019: Governance Package Separation

## Tag
#adr_019

## Status
Accepted

## Date
2026-06-21

## Scope
ModularityKit.Mutator
ModularityKit.Mutator.Governance

## Context

`ModularityKit.Mutator` started as focused mutation runtime:

- mutation execution
- policy evaluation
- audit and history basics
- side effects
- metrics and interception

At the same time, the roadmap and emerging API gaps point toward broader governance model:

- mutation requests
- pending execution lifecycle
- approval workflows
- version aware deferred execution
- governance-specific persistence and query capabilities
- compensation and resolution flows

Those concerns are related to mutation execution, but they are not the same layer.

If they are added directly into the core package, the main risk is that `ModularityKit.Mutator` turns from lightweight mutation runtime into heavy workflow and governance framework. That would make the core package harder to understand, harder to keep small, and harder to adopt for users who only need deterministic mutation execution.

## Decision

- Keep `ModularityKit.Mutator` as the core execution package.
- Introduce `ModularityKit.Mutator.Governance` as separate package in the same repository.
- Place governance specific abstractions and runtime components under the governance package rather than in the core runtime.
- Keep both packages in one repository for now, with separate project files and separate package boundaries.

Current package split:

### Core: `ModularityKit.Mutator`

Responsible for:

- mutation execution
- policy evaluation
- audit and history basics
- side effects
- metrics
- interceptor pipeline

### Extension: `ModularityKit.Mutator.Governance`

Responsible for:

- `MutationRequest`
- pending mutation lifecycle
- request decisions and resolution
- approval-oriented contracts
- governance request storage contracts

## Design Rationale

- Preserves small and execution focused core package.
- Allows governance to evolve at different pace than the core runtime.
- Makes governance an opt in capability instead of default weight for all users.
- Keeps repo level development simple by avoiding an early split into multiple repositories.
- Provides a clean place for future packages such as persistence providers without polluting the core runtime surface.

## Consequences

### Positive

- The mutation engine stays focused on direct execution concerns.
- Governance can grow into a richer model without forcing all consumers to adopt it.
- Future packages such as `EntityFrameworkCore` or `PostgreSql` governance providers have natural home.
- The repository structure now reflects the architectural boundary explicitly.

### Negative

- Some concepts will span package boundaries and require careful API ownership.
- Documentation must explain clearly when a feature belongs to core versus governance.
- Cross-package evolution will need discipline to avoid circular design pressure.

## Follow up

- Keep new governance runtime features out of `ModularityKit.Mutator` unless they are fundamental to direct execution.
- Grow pending lifecycle, approval flow, and request storage inside `ModularityKit.Mutator.Governance`.
- Revisit repo/package boundaries only if governance becomes large enough to justify separate repository in the future.
76 changes: 76 additions & 0 deletions Docs/Decision/Adr/ADR_020_Governance_MutationRequest_Model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# ADR-020: Governance MutationRequest Model

## Tag
#adr_020

## Status
Accepted

## Date
2026-06-21

## Scope
ModularityKit.Mutator.Governance.Abstractions

## Context

The governance layer needs primary unit that can represent more than direct mutation execution.

Core runtime mutations are immediate execution objects. Governance needs model that can survive over time and carry:

- request identity
- state targeting
- mutation classification
- request context
- pending requirements
- request decisions
- version expectations

Without such a model, deferred execution would have to be represented through ad hoc flags on mutation results, which is too weak for approval, expiration, cancellation, and re-resolution scenarios.

## Decision

- Introduce `MutationRequest` as the primary governance aggregate.
- `MutationRequest` carries:
- `RequestId`
- `StateId`
- `StateType`
- `MutationType`
- `Intent`
- `Context`
- `Status`
- `PendingReason`
- `Requirements`
- `Decisions`
- `ExpectedStateVersion`
- `ExpiresAt`
- `CreatedAt`
- `UpdatedAt`
- request-level `Metadata`
- Provide factory methods for:
- `Pending(...)`
- `Approved(...)`

## Design Rationale

- Gives governance durable model that is distinct from direct mutation execution.
- Keeps request lifecycle concerns out of the core `MutationResult`.
- Preserves enough context to support future approval, persistence, and re-execution flows.
- Makes version-aware deferred execution possible without leaking governance concerns into the core package.

## Consequences

### Positive

- Governance now has clear primary aggregate.
- Future approval and pending lifecycle features have stable model to build on.
- Request level persistence and query APIs have a natural root entity.

### Negative

- Some mutation data is now represented in both core and governance layers, with different purposes.
- Governance logic will need discipline to avoid turning `MutationRequest` into an unbounded bag of state.

## Related ADRs

- ADR-019: Governance Package Separation
73 changes: 73 additions & 0 deletions Docs/Decision/Adr/ADR_021_Governance_Pending_Mutation_Lifecycle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# ADR-021: Governance Pending Mutation Lifecycle

## Tag
#adr_021

## Status
Accepted

## Date
2026-06-21

## Scope
ModularityKit.Mutator.Governance.Abstractions

## Context

Not every governed mutation should execute immediately.

Governance needs an explicit lifecycle for requests that are:

- waiting for approval
- blocked on external checks
- delayed by scheduling
- waiting on dependencies
- held for quota or manual review

If pending execution is represented only as denial or boolean flag, the runtime cannot express expiration, cancellation, superseding, or eventual execution.

## Decision

- Introduce `MutationRequestStatus` as the lifecycle status enum for governed requests.
- Supported statuses:
- `Created`
- `Pending`
- `Approved`
- `Rejected`
- `Canceled`
- `Expired`
- `Superseded`
- `Executed`
- Introduce `PendingMutationReason` to explain why a request is pending.
- Supported pending reasons:
- `Approval`
- `ExternalCheck`
- `Schedule`
- `Dependency`
- `Quota`
- `ManualReview`

## Design Rationale

- Separates lifecycle state from lifecycle cause.
- Makes pending execution first class governance concept instead of terminal failure state.
- Supports future query APIs such as “all pending approvals” or “all expired requests”.
- Allows approval flow to be one specialization of pending execution, rather than the only pending model.

## Consequences

### Positive

- Governance can represent deferred execution explicitly.
- Approval workflows, external checks, and scheduling can share one lifecycle model.
- Future persistence and query layers have stable status dimensions to index.

### Negative

- Lifecycle semantics now need to be enforced consistently in runtime logic that does not exist yet.
- Some statuses, especially `Superseded` and `Executed`, will require careful definition once version-aware execution is implemented.

## Related ADRs

- ADR-019: Governance Package Separation
- ADR-020: Governance MutationRequest Model
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# ADR-022: Governance Request Decisions and Storage

## Tag
#adr_022

## Status
Accepted

## Date
2026-06-21

## Scope
ModularityKit.Mutator.Governance.Abstractions
ModularityKit.Mutator.Governance.Runtime

## Context

Once mutation requests become durable governance objects, they need:

- a history of lifecycle decisions
- a storage contract
- a minimal runtime implementation for local development and tests

Without decisions, the request only shows current state and loses governance history.
Without a store contract, governance cannot grow into persistence or query features.

## Decision

- Introduce `MutationRequestDecision` as the record of lifecycle transition or governance action.
- Introduce `MutationRequestDecisionType` with:
- `Submitted`
- `Approved`
- `Rejected`
- `Canceled`
- `Expired`
- `Superseded`
- `Executed`
- Introduce `IMutationRequestStore` with operations for:
- storing request
- retrieving by request id
- retrieving by state id
- retrieving pending requests
- Provide `InMemoryMutationRequestStore` as the first runtime implementation.

## Design Rationale

- Keeps current request state and decision history together at the model level.
- Establishes a storage seam before adding provider specific persistence packages.
- Mirrors the existing core approach of starting with in-memory runtime implementations before introducing durable adapters.

## Consequences

### Positive

- Governance now has durable decision log model.
- The storage contract is in place for future provider packages.
- Examples, tests, and local runtime flows can use `InMemoryMutationRequestStore` immediately.

### Negative

- Decision history and current status can drift if future runtime transitions are not applied carefully.
- Query capabilities are still minimal and intentionally incomplete at this stage.

## Related ADRs

- ADR-019: Governance Package Separation
- ADR-020: Governance MutationRequest Model
- ADR-021: Governance Pending Mutation Lifecycle
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# ADR-023: Governance Versioned Request Resolution

## Tag
#adr_023

## Status
Proposed

## Date
2026-06-21

## Scope
ModularityKit.Mutator.Governance

## Context

Pending mutation requests may be resolved long after they were created.

Example:

- request created against state version `v10`
- request enters `PendingApproval`
- approval happens after the state has advanced to `v15`

At that point, governance must define what approval means:

- execute against the latest state
- reject as stale
- require re-approval
- attempt re-validation and branch from there

This is a governance concern, not just a core mutation concern, because it only appears once requests can survive beyond immediate execution.

## Decision

The governance package should adopt explicit version-aware request resolution semantics.

Expected direction:

- `MutationRequest` keeps an `ExpectedStateVersion`
- request resolution must compare current state version with expected version
- stale requests must not silently execute without an explicit rule
- runtime resolution should choose among:
- re-validate and execute against latest state
- reject as stale
- require renewed approval

The exact resolution policy is intentionally left open for the first runtime implementation.

## Design Rationale

- Approval and deferred execution are not safe without explicit state version semantics.
- Silent execution on drifted state would weaken governance guarantees.
- The model already contains the right seam through `ExpectedStateVersion`.

## Consequences

### Positive

- Governance runtime will have explicit semantics for stale approvals.
- Deferred execution becomes safer and more auditable.

### Negative

- This introduces additional policy and runtime complexity.
- Different domains may want different stale resolution strategies.

## Related ADRs

- ADR-020: Governance MutationRequest Model
- ADR-021: Governance Pending Mutation Lifecycle
Loading
Loading