Add TemporalRepository<T> + ScopeGuardRepository<T> decorators #9

Closed
opened 2026-04-27 21:05:23 +02:00 by uwe.admin · 2 comments
Owner

Builds on uwe.admin/webapp-scaffold#8. Adds the two cross-cutting decorators that wrap any Repository<T> to enforce temporal versioning and resource-scope authorization respectively.

Scope

TemporalRepository<TDto> (requires TDto : ITemporalEntity)

  • Wraps an inner Repository<TDto>
  • On save: closes the previous version (sets valid_until = now) and inserts a new row with valid_from = now, valid_until = '9999-12-31T23:59:59Z'
  • On findByEntityId(at: TemporalAt): filters by valid_from <= at < valid_until
  • Implements IHistoryRepository<TDto>: history(entityId) returns all versions ordered by valid_from

ScopeGuardRepository<TDto>

  • Wraps an inner Repository<TDto>
  • Generic — does not know about "property" specifically. Takes a guard predicate as a constructor parameter:
    std::function<bool(const ActorContext&, const TDto&)> isAllowed;
    
  • On every method, evaluates the predicate against the resolved DTO; throws / denies on false.
  • The fewo-webapp-specific "property-scope" guard is wired up in fewo-webapp, not in webapp-scaffold.

Out of scope

  • Wiring decorators into any concrete repo (that's the pilot issue)
  • The fewo-webapp property-scope guard predicate itself

Acceptance

  • Both decorators compile against the interfaces from uwe.admin/webapp-scaffold#8
  • Unit tests against the in-memory fake show:
    • Temporal save closes the prior version
    • Live read returns only the row with valid_until = sentinel
    • Point-in-time read returns the version live at that time
    • History returns all versions in order
    • Scope guard short-circuits when the predicate returns false
Builds on uwe.admin/webapp-scaffold#8. Adds the two cross-cutting decorators that wrap any `Repository<T>` to enforce temporal versioning and resource-scope authorization respectively. ## Scope ### `TemporalRepository<TDto>` (requires `TDto : ITemporalEntity`) - Wraps an inner `Repository<TDto>` - On `save`: closes the previous version (sets `valid_until = now`) and inserts a new row with `valid_from = now`, `valid_until = '9999-12-31T23:59:59Z'` - On `findByEntityId(at: TemporalAt)`: filters by `valid_from <= at < valid_until` - Implements `IHistoryRepository<TDto>`: `history(entityId)` returns all versions ordered by `valid_from` ### `ScopeGuardRepository<TDto>` - Wraps an inner `Repository<TDto>` - Generic — does **not** know about "property" specifically. Takes a guard predicate as a constructor parameter: ```cpp std::function<bool(const ActorContext&, const TDto&)> isAllowed; ``` - On every method, evaluates the predicate against the resolved DTO; throws / denies on false. - The fewo-webapp-specific "property-scope" guard is wired up in fewo-webapp, not in webapp-scaffold. ## Out of scope - Wiring decorators into any concrete repo (that's the pilot issue) - The fewo-webapp property-scope guard predicate itself ## Acceptance - Both decorators compile against the interfaces from uwe.admin/webapp-scaffold#8 - Unit tests against the in-memory fake show: - Temporal save closes the prior version - Live read returns only the row with `valid_until = sentinel` - Point-in-time read returns the version live at that time - History returns all versions in order - Scope guard short-circuits when the predicate returns false
Author
Owner

Agent Evaluation

Drafted as part of the planning thread (parent: uwe.admin/fewo-webapp#458). Body above is the evaluation.

Feasibility: Straightforward — the temporal logic is well-understood (closes prior version on save, sentinel-based live read), and the scope-guard is a generic predicate wrapper. No SQL involved. Depends on uwe.admin/webapp-scaffold#8 landing first.

Impact: This is where the per-entity duplication finally collapses. Once both decorators are in scaffold, every concrete repo gets temporal + scoping for free.

Effort: Small–Medium. Two decorator classes plus unit tests against the in-memory fake from #8.

Recommendation: Accept. Implementation should not begin until #8 is merged.

## Agent Evaluation Drafted as part of the planning thread (parent: uwe.admin/fewo-webapp#458). Body above is the evaluation. **Feasibility:** Straightforward — the temporal logic is well-understood (closes prior version on save, sentinel-based live read), and the scope-guard is a generic predicate wrapper. No SQL involved. Depends on uwe.admin/webapp-scaffold#8 landing first. **Impact:** This is where the per-entity duplication finally collapses. Once both decorators are in scaffold, every concrete repo gets temporal + scoping for free. **Effort:** Small–Medium. Two decorator classes plus unit tests against the in-memory fake from #8. **Recommendation:** Accept. Implementation should not begin until #8 is merged.
uwe.admin added the
evaluated
label 2026-04-27 21:07:59 +02:00
Author
Owner

Closed in favour of uwe.admin/oatpp-authkit#8 per the Option A decision (this issue's #8 thread). C++ work belongs in oatpp-authkit, not in this TypeScript scaffold package.

Closed in favour of uwe.admin/oatpp-authkit#8 per the Option A decision (this issue's #8 thread). C++ work belongs in oatpp-authkit, not in this TypeScript scaffold package.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: uwe.admin/webapp-scaffold#9
No description provided.