Skip to main content

Rule Model

Decision Contexts

Decisions are always evaluated within a context.

Examples:

  • allowlist.general
  • comment
  • publish
  • apply
  • governance.vote

A rule never applies globally without a context.

Rule Interface

interface Rule {
id: string;
context: string | "*";
when: (signals: NormalizedSignals) => boolean;
decision: "ALLOW" | "DENY" | "ALLOW_WITH_LIMITS";
reason: string;
confidenceDelta: number;
}

Rule Evaluation Order

  1. Fallback Rules (insufficient signals → fail fast)
  2. Hard-Deny Rules (fail fast)
  3. Allow Rules
  4. Allow-With-Limits Rules
  5. Default Deny (safe fallback)

Semantics: First-match wins. The engine returns immediately when a rule matches. This is intentional — rules are ordered by priority, not accumulated.

Rule Catalog

The engine evaluates rules in a strict 5-phase order. The first matching rule determines the result.

Phase 1: Fallback Rules (Signal Quality)

Checked first. Handles missing data.

IDConditionDecisionConfidence Δ
deny_no_signalssignalCoverage == 0DENY-100
limit_partial_signalssignalCoverage < 0.5ALLOW_WITH_LIMITS-30

Phase 2: Hard Deny Rules (Critical Risks)

Risk checks that apply globally (*).

IDConditionDecisionConfidence Δ
deny_spamspamRisk is HIGH or VERY_HIGHDENY-100
deny_low_social_trustsocialTrust < NEUTRALDENY-100
deny_critical_trusttrust == VERY_LOWDENY-100

Phase 3: Allow Rules (Positive Access)

Granting full access based on merit.

IDContextCondition (Summary)Confidence Δ
allow_strong_builderallowlist.generalbuilder is EXPERT OR (builder ≥ ADVANCED AND socialTrust ≥ HIGH)+30
allow_strong_creatorallowlist.generalcreator is EXPERT OR (creator ≥ ADVANCED AND socialTrust ≥ HIGH)+30
allow_high_trustallowlist.generaltrust ≥ HIGH AND socialTrust ≥ HIGH+25
allow_comment_trustedcommenttrust ≥ NEUTRAL AND socialTrust ≥ NEUTRAL+15
allow_publish_verifiedpublishtrust ≥ HIGH AND socialTrust ≥ HIGH AND (builder/creator ≥ INTERMEDIATE)+25
allow_apply_qualifiedapplytrust ≥ NEUTRAL AND (builder/creator ≥ ADVANCED)+20
allow_governance_votegovernance.votetrust ≥ HIGH AND socialTrust ≥ NEUTRAL AND recencyDays ≤ 30+20

Phase 4: Allow With Limits (Conditional Access)

Granting restricted access.

IDContextCondition (Summary)DecisionConfidence Δ
probation_inactiveallowlist.generaltrust ≥ NEUTRAL AND recencyDays > 14ALLOW_WITH_LIMITS-10
probation_new_userallowlist.generaltrust ≥ NEUTRAL AND socialTrust ≥ NEUTRAL (No skills)ALLOW_WITH_LIMITS-15
probation_mixed_signalsallowlist.generaltrust ≥ HIGH AND socialTrust < NEUTRALALLOW_WITH_LIMITS-10
limit_comment_newcommenttrust ≥ LOW AND signalCoverage ≥ 0.5ALLOW_WITH_LIMITS-5
limit_publish_unverifiedpublishtrust ≥ NEUTRAL AND socialTrust ≥ NEUTRALALLOW_WITH_LIMITS-10
limit_governance_inactivegovernance.votetrust ≥ HIGH AND recencyDays (30-90]ALLOW_WITH_LIMITS-15

Phase 5: Default Deny

If no rule matches, the decision is DENY (Confidence: LOW).

Rule Implementation Examples

Fallback Rules

{
id: "deny_no_signals",
context: "*",
when: s => s.signalCoverage === 0,
decision: "DENY",
reason: "No reputation signals available",
confidenceDelta: -100
}

Hard-Deny Rules

{
id: "deny_spam",
context: "*",
when: s => s.spamRisk === "HIGH" || tierLt(s.socialTrust, "NEUTRAL"),
decision: "DENY",
reason: "High spam risk or low social trust detected",
confidenceDelta: -100
}

Allow Rules

{
id: "allow_strong_builder",
context: "allowlist.general",
when: s =>
s.builder === "EXPERT" ||
(s.builder === "ADVANCED" && tierGte(s.socialTrust, "HIGH")),
decision: "ALLOW",
reason: "Strong builder credibility with sufficient social trust",
confidenceDelta: +30
}

Allow-With-Limits Rules

{
id: "probation_inactive",
context: "allowlist.general",
when: s =>
tierGte(s.trust, "NEUTRAL") && s.recencyDays > 14,
decision: "ALLOW_WITH_LIMITS",
reason: "Trustworthy but recently inactive",
confidenceDelta: -10
}