Phase 2 Trust Extraction - Assessment & Path Forward
Current PR Status: REJECT
PR #882 contains a fundamental architectural violation that cannot be salvaged through incremental fixes.
The Critical Flaw: Reverse Meaning Firewall
What Went Wrong
The implementation maps PolicyOracle ConstraintSet back to domain type TrustClass:
// ❌ ARCHITECTURAL VIOLATION
let trust_class = match constraints.max_topics {
Some(n) if n >= 500 => TrustClass::Federated,
Some(n) if n >= 100 => TrustClass::Partner,
Some(n) if n >= 25 => TrustClass::Known,
_ => TrustClass::Isolated,
};
Why This Is Wrong
The meaning firewall exists to prevent kernel code from understanding domain semantics:
Trust App (Domain) PolicyOracle (Firewall) Kernel (Mechanics)
------------------ ----------------------- ------------------
TrustGraph ↓ ↓
compute_trust_score() score_to_constraints() constraints only
TrustClass semantics ConstraintSet (generic) NO domain knowledge
↓
[FIREWALL BOUNDARY]
↓
Kernel NEVER sees:
- TrustClass
- Trust scores
- Why constraints exist
By reconstructing TrustClass from max_topics, the kernel is reverse-engineering domain semantics, which:
- Defeats the abstraction
- Couples kernel to trust app internals
- Creates hidden dependencies on constraint value ranges
- Makes it impossible to change trust scoring without breaking kernel code
Infection Count
Current TrustClass/TrustGraph references in affected crates:
icn-gossip: 30+ references (including tests)
icn-net: ~20 references
icn-gateway: ~15 references
icn-ledger: ~5 references
The Correct Approach
1. Refactor AccessControl Enum (icn-gossip)
Current (Wrong):
pub enum AccessControl {
Open,
TrustClass(TrustClass), // ❌ Domain type in kernel
Allowlist(HashSet<Did>),
}
Correct:
pub enum AccessControl {
Open,
MinTopics(u32), // ✅ Generic constraint
Allowlist(HashSet<Did>),
}
2. Use Constraints Directly (All Kernel Crates)
Wrong:
let trust_class = map_constraints_to_class(constraints); // ❌
let limit = TrustResourceLimits::for_trust_class(trust_class);
Correct:
let max_topics = constraints.max_topics.unwrap_or(25); // ✅
if current_topics >= max_topics {
return Err(LimitExceeded);
}
3. Eliminate TrustClass from Kernel Types
Rename and refactor:
TrustResourceLimits→ResourceLimits(remove TrustClass field)trust_class: TrustClass→ use constraint values directly- Helper functions take
&ConstraintSet, notTrustClass
Implementation Order (Correct)
Estimated Timeline
| Phase | Scope | Estimated Effort |
|---|---|---|
| 2.2a | icn-gossip | 1-2 days focused work |
| 2.2b | icn-ledger | 1 day |
| 2.2c | icn-net | 1-2 days |
| 2.2d | icn-gateway | 1 day |
| 2.3 | icn-core integration | 1 day |
| Total | 5-7 days |
Note: Each phase should be a separate PR for reviewability.
Phase 2.2a: icn-gossip
Prerequisite: Refactor AccessControl enum first
- Remove all
TrustClassreferences - Update
can_subscribe()/can_publish()to useMinTopics(u32) - Replace
topics_per_peer_limit(TrustClass)withtopics_per_peer_limit(&ConstraintSet) - Update all tests to use
AllowAllOracleor mock oracle
Phase 2.2b: icn-ledger
- Replace
TrustGraph::compute_trust_score()withoracle.evaluate() - Extract
credit_multiplierfromConstraintSet - Never reconstruct trust scores from multiplier
Phase 2.2c: icn-net
- Replace
trust_graphfield withpolicy_oracle - Extract
RateLimitfromConstraintSetdirectly - Update
RateLimitConfigto not referenceTrustClass
Phase 2.2d: icn-gateway
- Remove hardcoded thresholds (0.7, 0.4, 0.1)
- Use
constraints.rate_limitdirectly - No manual trust-to-rate mapping
Phase 2.3: icn-core supervisor
- Wire
AllowAllOracleduring bootstrap - Load trust app and register
TrustPolicyOracle - Pass oracle to all actors
Anti-Patterns to Avoid
❌ Never Do This
- Reverse mapping:
constraints → TrustClass - Temporary bridges: They become permanent
- Hardcoded thresholds:
if score >= 0.7 - Domain type reconstruction: Inferring semantics from constraints
✅ Always Do This
- Use constraints directly:
constraints.max_topics - Default gracefully:
.unwrap_or(default_value) - Refactor kernel types: Remove domain type fields
- Test with mock oracles:
AllowAllOracle,DenyAllOracle
Verification Criteria
After proper implementation:
# No TrustClass in kernel crates
grep -r 'TrustClass' icn/crates/icn-{gossip,net,gateway,ledger}/src \
&& echo 'FAIL: Domain types in kernel' \
|| echo 'PASS: Meaning firewall intact'
# No TrustGraph in kernel crates
grep -r 'TrustGraph' icn/crates/icn-{gossip,net,gateway,ledger}/src \
&& echo 'FAIL: Direct graph access' \
|| echo 'PASS: Oracle abstraction enforced'
# Tests compile and pass
cargo test -p icn-gossip -p icn-net -p icn-ledger -p icn-gateway
Lessons Learned
For Future PRs
Add to project rules:
- Code review checklist: Reject PRs that map constraints to domain types
- Architecture doc: Document the meaning firewall with examples
- Test patterns: Provide templates for oracle-based tests
- Incremental refactoring: Refactor kernel types before replacing trust lookups
Why This Failed
- Incomplete refactoring: Changed lookup mechanism but not the kernel types
- Expedience over correctness: "Temporary bridge" seemed faster than proper refactor
- Missing big picture: Focused on removing fields, not removing domain knowledge
Recommendation
Close PR #882 and restart with proper approach:
- Create sub-issues (2.2a through 2.3)
- Start with icn-gossip AccessControl refactor
- Ensure each crate passes firewall verification before moving to next
- Update project rules with anti-patterns
- Final integration test with supervisor wiring
References
- Issue #857: Phase 2 - Trust Extraction
apps/trust/src/oracle.rs: Correct oracle implementationicn-kernel-api/src/authz.rs: PolicyOracle trait definition
Related Documents
- Phase 2 Status Summary - Current status and execution order
- Project Rules - Anti-patterns and code review checklist