Phase 0: Residual authority detection (baseline) #59

Merged
erikinkinen merged 3 commits from 0-residual-authority-detection-baseline into main 2026-03-03 12:38:56 +01:00
Owner

Summary

Implements Residual Authority Detection (Baseline) v0 for issue #18.

This adds a baseline residual-authority layer that detects unexpected direct reachability (actual - expected), introduces non-blocking runtime hook reporting, and provides forward-looking residual interfaces for later revocation phases.

Closes #18.

What’s Included

1) Baseline residue concept and detector (aes::core)

Added:

  • core/include/aes/core/residual_authority.hpp
  • core/src/residual_authority.cpp

New public types/APIs:

  • ResidualBaselineSpec
    • expected_objects_from_subject: map<SubjectId, vector<ObjectId>>
    • expected_subjects_to_object: map<ObjectId, vector<SubjectId>>
  • UnexpectedFromSubject
  • UnexpectedToObject
  • UnexpectedReachabilityFinding (variant)
  • detect_unexpected_reachability(...)

Behavior:

  • Computes residue as actual_reachable - expected_reachable
  • Uses existing direct-edge reachability semantics (#17, non-empty rights only)
  • Strict validation:
    • invalid IDs -> Errc::InvalidArgument
    • missing IDs -> Errc::NotFound
    • invalid graph -> Errc::InvariantViolation
  • Deterministic output order:
    • subject findings first (ascending subject id)
    • object findings next (ascending object id)
  • Baseline only reports unexpected extras; missing expected reachability is not flagged in v0

Also documented baseline concept and non-goals in:

  • docs/phase0.md (new section under Phase 0 core)

2) Unexpected-reachability runtime hooks (aes::sim)

Added:

  • sim/include/aes/sim/residual_hooks.hpp
  • sim/src/residual_hooks.cpp

New public types/APIs:

  • UnexpectedReachabilityReport
    • time
    • event_id
    • analysis_error
    • findings
  • UnexpectedReachabilityHook interface
  • NoopUnexpectedReachabilityHook
  • Additive Engine APIs:
    • step_with_unexpected_reachability_hook(...)
    • run_with_unexpected_reachability_hook(...)

Behavior:

  • Hook logic runs only after successful event application
  • Report uses post-step time and history.back().id
  • If detection finds unexpected reachability: hook called once for that step
  • If detection fails: hook called with analysis_error and empty findings
  • Detection findings/errors are observational and do not abort step/run
  • Event application failures still abort run_with_unexpected_reachability_hook (same as normal run behavior)

3) Later-phase residual stubs (aes::sim)

Added:

  • sim/include/aes/sim/residual_pipeline.hpp

New stub interfaces:

  • ResidualExpectationProvider
  • ResidualDetector
  • NoopResidualExpectationProvider (returns empty baseline)
  • NoopResidualDetector (returns empty findings)

These are intentionally additive and decoupled from revocation policy semantics.

Build / Wiring Changes

  • core/CMakeLists.txt: adds src/residual_authority.cpp
  • sim/CMakeLists.txt: adds src/residual_hooks.cpp
  • tests/CMakeLists.txt: adds:
    • aes_residual_authority_tests
    • aes_residual_hooks_tests
    • aes_residual_pipeline_stubs_tests

Tests Added

  • tests/residual_authority_tests.cpp
    • exact-match baseline -> no findings
    • subject-side unexpected detection
    • object-side unexpected detection
    • dedupe behavior
    • empty-right edge exclusion
    • strict invalid/missing ID handling
    • deterministic ordering
    • invariant guard behavior
  • tests/residual_hooks_tests.cpp
    • hook invocation on findings
    • no invocation when no findings
    • analysis error reporting
    • no hook on failed event step
    • run behavior: continue on findings, stop on event failure
  • tests/residual_pipeline_stubs_tests.cpp
    • no-op provider/detector behavior
    • polymorphic usage smoke checks

Commit Breakdown

  1. Phase 0: Define baseline residue concept (#18)
  2. Phase 0: Implement unexpected reachability hooks (#18)
  3. Phase 0: Stub residual interfaces for later phases (#18)

Validation

Executed after each commit:

  • cmake --build _build
  • ctest --test-dir _build --output-on-failure

Final result: all tests passing (29/29).

## Summary Implements **Residual Authority Detection (Baseline) v0** for issue #18. This adds a baseline residual-authority layer that detects **unexpected direct reachability** (`actual - expected`), introduces **non-blocking runtime hook reporting**, and provides **forward-looking residual interfaces** for later revocation phases. Closes #18. ## What’s Included ### 1) Baseline residue concept and detector (`aes::core`) Added: - `core/include/aes/core/residual_authority.hpp` - `core/src/residual_authority.cpp` New public types/APIs: - `ResidualBaselineSpec` - `expected_objects_from_subject: map<SubjectId, vector<ObjectId>>` - `expected_subjects_to_object: map<ObjectId, vector<SubjectId>>` - `UnexpectedFromSubject` - `UnexpectedToObject` - `UnexpectedReachabilityFinding` (`variant`) - `detect_unexpected_reachability(...)` Behavior: - Computes residue as `actual_reachable - expected_reachable` - Uses existing direct-edge reachability semantics (`#17`, non-empty rights only) - Strict validation: - invalid IDs -> `Errc::InvalidArgument` - missing IDs -> `Errc::NotFound` - invalid graph -> `Errc::InvariantViolation` - Deterministic output order: - subject findings first (ascending subject id) - object findings next (ascending object id) - Baseline only reports unexpected extras; missing expected reachability is not flagged in v0 Also documented baseline concept and non-goals in: - `docs/phase0.md` (new section under Phase 0 core) ### 2) Unexpected-reachability runtime hooks (`aes::sim`) Added: - `sim/include/aes/sim/residual_hooks.hpp` - `sim/src/residual_hooks.cpp` New public types/APIs: - `UnexpectedReachabilityReport` - `time` - `event_id` - `analysis_error` - `findings` - `UnexpectedReachabilityHook` interface - `NoopUnexpectedReachabilityHook` - Additive `Engine` APIs: - `step_with_unexpected_reachability_hook(...)` - `run_with_unexpected_reachability_hook(...)` Behavior: - Hook logic runs only after successful event application - Report uses post-step `time` and `history.back().id` - If detection finds unexpected reachability: hook called once for that step - If detection fails: hook called with `analysis_error` and empty findings - Detection findings/errors are observational and do not abort step/run - Event application failures still abort `run_with_unexpected_reachability_hook` (same as normal run behavior) ### 3) Later-phase residual stubs (`aes::sim`) Added: - `sim/include/aes/sim/residual_pipeline.hpp` New stub interfaces: - `ResidualExpectationProvider` - `ResidualDetector` - `NoopResidualExpectationProvider` (returns empty baseline) - `NoopResidualDetector` (returns empty findings) These are intentionally additive and decoupled from revocation policy semantics. ## Build / Wiring Changes - `core/CMakeLists.txt`: adds `src/residual_authority.cpp` - `sim/CMakeLists.txt`: adds `src/residual_hooks.cpp` - `tests/CMakeLists.txt`: adds: - `aes_residual_authority_tests` - `aes_residual_hooks_tests` - `aes_residual_pipeline_stubs_tests` ## Tests Added - `tests/residual_authority_tests.cpp` - exact-match baseline -> no findings - subject-side unexpected detection - object-side unexpected detection - dedupe behavior - empty-right edge exclusion - strict invalid/missing ID handling - deterministic ordering - invariant guard behavior - `tests/residual_hooks_tests.cpp` - hook invocation on findings - no invocation when no findings - analysis error reporting - no hook on failed event step - run behavior: continue on findings, stop on event failure - `tests/residual_pipeline_stubs_tests.cpp` - no-op provider/detector behavior - polymorphic usage smoke checks ## Commit Breakdown 1. `Phase 0: Define baseline residue concept (#18)` 2. `Phase 0: Implement unexpected reachability hooks (#18)` 3. `Phase 0: Stub residual interfaces for later phases (#18)` ## Validation Executed after each commit: - `cmake --build _build` - `ctest --test-dir _build --output-on-failure` Final result: all tests passing (`29/29`).
erikinkinen added this to the Phase 0 milestone 2026-03-03 12:22:25 +01:00
Phase 0: Stub residual interfaces for later phases (#18)
All checks were successful
ci / smoke (push) Successful in 13s
clang-format / check-format (push) Successful in 8s
markdownlint / markdown-lint (push) Successful in 10s
ci / smoke (pull_request) Successful in 14s
clang-format / check-format (pull_request) Successful in 8s
markdownlint / markdown-lint (pull_request) Successful in 10s
c84d60ae66
Sign in to join this conversation.
No reviewers
No milestone
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
erikinkinen/AES!59
No description provided.