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
9 changes: 5 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@
presentations all remain obstructed until real bounded grant validation
exists.
- `warp-core` now has an Echo-owned capability grant intent obstruction
skeleton. `CapabilityGrantIntentRegistry` records well-formed submitted
authority intents deterministically, obstructs malformed, duplicate, and
identity-incomplete grant intents, and keeps all submissions from becoming
authority until future witnessed grant admission exists.
skeleton. `CapabilityGrantIntentGate` records well-formed submitted authority
intents deterministically, obstructs malformed, missing-issuer,
invalid-delegation, scope-escalation, replay/duplicate, and unsupported-policy
grant intents, and keeps all submissions from becoming authority until future
witnessed grant admission exists.
- Echo-owned WASM package boundary tooling: `scripts/build-warp-wasm-package.sh`
now builds `crates/warp-wasm/pkg` with the bundler target and the package
export smoke test imports `crates/warp-wasm/pkg/rmg_wasm.js` to verify the
Expand Down
16 changes: 8 additions & 8 deletions crates/warp-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,14 +248,14 @@ pub use optic::{
StagedIntent, StagedIntentReason, WitnessBasis, WorldlineHeadOptic,
};
pub use optic_artifact::{
AuthorityContext, AuthorityPolicy, CapabilityGrantIntent, CapabilityGrantIntentGate,
CapabilityGrantIntentObstruction, CapabilityGrantIntentOutcome, CapabilityGrantIntentPosture,
OpticAdmissionRequirements, OpticAdmissionTicketPosture, OpticApertureRequest, OpticArtifact,
OpticArtifactHandle, OpticArtifactOperation, OpticArtifactRegistrationError,
OpticArtifactRegistry, OpticBasisRequest, OpticCapabilityPresentation, OpticInvocation,
OpticInvocationAdmissionOutcome, OpticInvocationObstruction, OpticRegistrationDescriptor,
PrincipalRef, RegisteredOpticArtifact, OPTIC_ADMISSION_TICKET_POSTURE_KIND,
OPTIC_ARTIFACT_HANDLE_KIND,
AuthorityContext, AuthorityPolicy, AuthorityPolicyEvaluation, CapabilityGrantIntent,
CapabilityGrantIntentGate, CapabilityGrantIntentObstruction, CapabilityGrantIntentOutcome,
CapabilityGrantIntentPosture, OpticAdmissionRequirements, OpticAdmissionTicketPosture,
OpticApertureRequest, OpticArtifact, OpticArtifactHandle, OpticArtifactOperation,
OpticArtifactRegistrationError, OpticArtifactRegistry, OpticBasisRequest,
OpticCapabilityPresentation, OpticInvocation, OpticInvocationAdmissionOutcome,
OpticInvocationObstruction, OpticRegistrationDescriptor, PrincipalRef, RegisteredOpticArtifact,
OPTIC_ADMISSION_TICKET_POSTURE_KIND, OPTIC_ARTIFACT_HANDLE_KIND,
};
pub use playback::{CursorReceipt, TruthFrame, TruthSink};
pub use provenance_store::{
Expand Down
55 changes: 51 additions & 4 deletions crates/warp-core/src/optic_artifact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,30 @@ pub struct AuthorityPolicy {
pub policy_id: String,
}

/// Obstruction-only authority policy evaluation posture.
///
/// This is vocabulary, not governance. It lets Echo name policy failure
/// surfaces without accepting a grant intent, issuing a receipt, or treating a
/// policy shape as trusted authority.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AuthorityPolicyEvaluation {
/// The proposed delegation basis is not valid for the authority change.
InvalidDelegation,
/// The proposed grant would exceed the issuer's authority scope.
ScopeEscalation,
/// Echo does not have a supported authority policy implementation yet.
Unsupported,
}

/// Authority context supplied when proposing a capability grant intent.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AuthorityContext {
/// Principal whose prior authority is claimed for proposing the grant.
pub issuer: Option<PrincipalRef>,
/// Policy that should evaluate the issuer's authority.
pub policy: Option<AuthorityPolicy>,
/// Obstruction-only policy evaluation posture.
pub policy_evaluation: AuthorityPolicyEvaluation,
}

/// Causal authority intent submitted to Echo for future grant admission.
Expand Down Expand Up @@ -203,8 +220,12 @@ pub enum CapabilityGrantIntentObstruction {
MissingIssuerAuthority,
/// The grant intent is structurally unusable.
MalformedGrantIntent,
/// The proposed delegation basis is invalid.
InvalidDelegation,
/// The proposed scope would exceed the issuer's authority.
ScopeEscalation,
/// Echo already saw a grant intent with the supplied intent id.
DuplicateGrantIntent,
ReplayOrDuplicateIntent,
/// No real authority policy exists in this slice.
UnsupportedAuthorityPolicy,
}
Expand Down Expand Up @@ -357,7 +378,7 @@ impl CapabilityGrantIntentGate {
authority_context: AuthorityContext,
) -> CapabilityGrantIntentOutcome {
let obstruction = self.classify_capability_grant_intent(&intent, &authority_context);
if obstruction == CapabilityGrantIntentObstruction::UnsupportedAuthorityPolicy {
if Self::records_submitted_intent(obstruction) {
self.intents_by_id
.insert(intent.intent_id.clone(), intent.clone());
}
Expand Down Expand Up @@ -401,7 +422,7 @@ impl CapabilityGrantIntentGate {
}

if self.intents_by_id.contains_key(&intent.intent_id) {
return CapabilityGrantIntentObstruction::DuplicateGrantIntent;
return CapabilityGrantIntentObstruction::ReplayOrDuplicateIntent;
}

let Some(issuer) = &authority_context.issuer else {
Expand All @@ -411,7 +432,33 @@ impl CapabilityGrantIntentGate {
return CapabilityGrantIntentObstruction::MissingIssuerAuthority;
}

CapabilityGrantIntentObstruction::UnsupportedAuthorityPolicy
let Some(policy) = &authority_context.policy else {
return CapabilityGrantIntentObstruction::UnsupportedAuthorityPolicy;
};
if policy.policy_id.is_empty() {
return CapabilityGrantIntentObstruction::UnsupportedAuthorityPolicy;
}

match authority_context.policy_evaluation {
AuthorityPolicyEvaluation::InvalidDelegation => {
CapabilityGrantIntentObstruction::InvalidDelegation
}
AuthorityPolicyEvaluation::ScopeEscalation => {
CapabilityGrantIntentObstruction::ScopeEscalation
}
AuthorityPolicyEvaluation::Unsupported => {
CapabilityGrantIntentObstruction::UnsupportedAuthorityPolicy
}
}
}

fn records_submitted_intent(obstruction: CapabilityGrantIntentObstruction) -> bool {
matches!(
obstruction,
CapabilityGrantIntentObstruction::InvalidDelegation
| CapabilityGrantIntentObstruction::ScopeEscalation
| CapabilityGrantIntentObstruction::UnsupportedAuthorityPolicy
)
}

fn obstructed_grant_intent(
Expand Down
158 changes: 135 additions & 23 deletions crates/warp-core/tests/capability_grant_intent_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
//! Regression tests for Echo-owned capability grant intent obstruction.

use warp_core::{
AuthorityContext, AuthorityPolicy, CapabilityGrantIntent, CapabilityGrantIntentGate,
CapabilityGrantIntentObstruction, CapabilityGrantIntentOutcome, CapabilityGrantIntentPosture,
PrincipalRef,
AuthorityContext, AuthorityPolicy, AuthorityPolicyEvaluation, CapabilityGrantIntent,
CapabilityGrantIntentGate, CapabilityGrantIntentObstruction, CapabilityGrantIntentOutcome,
CapabilityGrantIntentPosture, PrincipalRef,
};

fn principal(id: &str) -> PrincipalRef {
Expand Down Expand Up @@ -33,6 +33,7 @@ fn fixture_authority_context() -> AuthorityContext {
policy: Some(AuthorityPolicy {
policy_id: "authority-policy:fixture".to_owned(),
}),
policy_evaluation: AuthorityPolicyEvaluation::Unsupported,
}
}

Expand Down Expand Up @@ -110,24 +111,24 @@ fn capability_grant_intent_obstructs_missing_required_identity_as_malformed() {
}

#[test]
fn capability_grant_intent_obstructs_duplicate_grant_intent() {
fn capability_grant_intent_obstructs_replay_or_duplicate_grant_intent() {
let mut registry = CapabilityGrantIntentGate::new();
let first_intent = fixture_intent("intent:duplicate");
let duplicate_intent = fixture_intent("intent:duplicate");
let first_intent = fixture_intent("intent:replay");
let replay_intent = fixture_intent("intent:replay");

let first_outcome = registry.submit_grant_intent(first_intent, fixture_authority_context());
let duplicate_outcome =
registry.submit_grant_intent(duplicate_intent.clone(), fixture_authority_context());
let replay_outcome =
registry.submit_grant_intent(replay_intent.clone(), fixture_authority_context());

assert_eq!(
obstruction_for(&first_outcome),
CapabilityGrantIntentObstruction::UnsupportedAuthorityPolicy
);
assert_eq!(
duplicate_outcome,
replay_outcome,
expected_obstructed_posture(
&duplicate_intent,
CapabilityGrantIntentObstruction::DuplicateGrantIntent
&replay_intent,
CapabilityGrantIntentObstruction::ReplayOrDuplicateIntent
)
);
}
Expand All @@ -141,6 +142,7 @@ fn capability_grant_intent_obstructs_missing_issuer_authority() {
policy: Some(AuthorityPolicy {
policy_id: "authority-policy:fixture".to_owned(),
}),
policy_evaluation: AuthorityPolicyEvaluation::Unsupported,
};

let outcome = registry.submit_grant_intent(intent.clone(), authority_context);
Expand All @@ -154,6 +156,69 @@ fn capability_grant_intent_obstructs_missing_issuer_authority() {
);
}

#[test]
fn capability_grant_intent_obstructs_invalid_delegation() {
let mut registry = CapabilityGrantIntentGate::new();
let intent = fixture_intent("intent:invalid-delegation");
let authority_context = AuthorityContext {
issuer: Some(principal("principal:issuer")),
policy: Some(AuthorityPolicy {
policy_id: "authority-policy:fixture".to_owned(),
}),
policy_evaluation: AuthorityPolicyEvaluation::InvalidDelegation,
};

let outcome = registry.submit_grant_intent(intent.clone(), authority_context);

assert_eq!(
outcome,
expected_obstructed_posture(&intent, CapabilityGrantIntentObstruction::InvalidDelegation)
);
}

#[test]
fn capability_grant_intent_obstructs_scope_escalation() {
let mut registry = CapabilityGrantIntentGate::new();
let intent = fixture_intent("intent:scope-escalation");
let authority_context = AuthorityContext {
issuer: Some(principal("principal:issuer")),
policy: Some(AuthorityPolicy {
policy_id: "authority-policy:fixture".to_owned(),
}),
policy_evaluation: AuthorityPolicyEvaluation::ScopeEscalation,
};

let outcome = registry.submit_grant_intent(intent.clone(), authority_context);

assert_eq!(
outcome,
expected_obstructed_posture(&intent, CapabilityGrantIntentObstruction::ScopeEscalation)
);
}

#[test]
fn capability_grant_intent_obstructs_missing_policy_identity_as_unsupported_policy() {
let mut registry = CapabilityGrantIntentGate::new();
let intent = fixture_intent("intent:missing-policy-identity");
let authority_context = AuthorityContext {
issuer: Some(principal("principal:issuer")),
policy: Some(AuthorityPolicy {
policy_id: String::new(),
}),
policy_evaluation: AuthorityPolicyEvaluation::InvalidDelegation,
};

let outcome = registry.submit_grant_intent(intent.clone(), authority_context);

assert_eq!(
outcome,
expected_obstructed_posture(
&intent,
CapabilityGrantIntentObstruction::UnsupportedAuthorityPolicy
)
);
}

#[test]
fn capability_grant_intent_obstructs_unsupported_authority_policy() {
let mut registry = CapabilityGrantIntentGate::new();
Expand All @@ -172,29 +237,64 @@ fn capability_grant_intent_obstructs_unsupported_authority_policy() {

#[test]
fn capability_grant_intent_never_makes_grant_authority() {
let mut registry = CapabilityGrantIntentGate::new();
let intents = [
fixture_intent("intent:malformed-empty-rights"),
fixture_intent("intent:missing-issuer"),
fixture_intent("intent:unsupported-policy"),
];

let mut malformed = intents[0].clone();
let mut malformed = fixture_intent("intent:malformed-empty-rights");
malformed.rights.clear();

let mut malformed_registry = CapabilityGrantIntentGate::new();
let mut missing_issuer_registry = CapabilityGrantIntentGate::new();
let mut invalid_delegation_registry = CapabilityGrantIntentGate::new();
let mut scope_escalation_registry = CapabilityGrantIntentGate::new();
let mut replay_registry = CapabilityGrantIntentGate::new();
let mut unsupported_registry = CapabilityGrantIntentGate::new();

let missing_issuer = fixture_intent("intent:missing-issuer");
let invalid_delegation = fixture_intent("intent:invalid-delegation-never-authority");
let scope_escalation = fixture_intent("intent:scope-escalation-never-authority");
let replay = fixture_intent("intent:replay-never-authority");
let unsupported = fixture_intent("intent:unsupported-policy");

let replay_first_outcome =
replay_registry.submit_grant_intent(replay.clone(), fixture_authority_context());
let outcomes = [
registry.submit_grant_intent(malformed, fixture_authority_context()),
registry.submit_grant_intent(
intents[1].clone(),
malformed_registry.submit_grant_intent(malformed, fixture_authority_context()),
missing_issuer_registry.submit_grant_intent(
missing_issuer,
AuthorityContext {
issuer: None,
policy: Some(AuthorityPolicy {
policy_id: "authority-policy:fixture".to_owned(),
}),
policy_evaluation: AuthorityPolicyEvaluation::Unsupported,
},
),
registry.submit_grant_intent(intents[2].clone(), fixture_authority_context()),
invalid_delegation_registry.submit_grant_intent(
invalid_delegation,
AuthorityContext {
issuer: Some(principal("principal:issuer")),
policy: Some(AuthorityPolicy {
policy_id: "authority-policy:fixture".to_owned(),
}),
policy_evaluation: AuthorityPolicyEvaluation::InvalidDelegation,
},
),
scope_escalation_registry.submit_grant_intent(
scope_escalation,
AuthorityContext {
issuer: Some(principal("principal:issuer")),
policy: Some(AuthorityPolicy {
policy_id: "authority-policy:fixture".to_owned(),
}),
policy_evaluation: AuthorityPolicyEvaluation::ScopeEscalation,
},
),
replay_registry.submit_grant_intent(replay, fixture_authority_context()),
unsupported_registry.submit_grant_intent(unsupported, fixture_authority_context()),
];

assert_eq!(
obstruction_for(&replay_first_outcome),
CapabilityGrantIntentObstruction::UnsupportedAuthorityPolicy
);
assert_eq!(
obstruction_for(&outcomes[0]),
CapabilityGrantIntentObstruction::MalformedGrantIntent
Expand All @@ -205,6 +305,18 @@ fn capability_grant_intent_never_makes_grant_authority() {
);
assert_eq!(
obstruction_for(&outcomes[2]),
CapabilityGrantIntentObstruction::InvalidDelegation
);
assert_eq!(
obstruction_for(&outcomes[3]),
CapabilityGrantIntentObstruction::ScopeEscalation
);
assert_eq!(
obstruction_for(&outcomes[4]),
CapabilityGrantIntentObstruction::ReplayOrDuplicateIntent
);
assert_eq!(
obstruction_for(&outcomes[5]),
CapabilityGrantIntentObstruction::UnsupportedAuthorityPolicy
);
}
Loading
Loading