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: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@

### Added

- `warp-core` optic invocation admission now has a narrow ApertureResolution v0
boundary. Identity-covered invocations with exact fixture basis bytes
`basis-request:resolved-fixture:v0` and exact fixture aperture bytes
`aperture-request:resolved-fixture:v0` progress past aperture resolution and
still obstruct at `UnsupportedBudgetResolution`; unsupported aperture shapes
continue to obstruct at `UnsupportedApertureResolution`, and aperture
resolution remains unreachable when basis resolution fails. This does not
issue admission tickets, law witnesses, scheduler work, execution, budget
evaluation, runtime support checks, or successful grant validation.
- `warp-core` optic invocation admission now has a narrow BasisResolution v0
boundary. Identity-covered invocations with exact fixture basis bytes
`basis-request:resolved-fixture:v0` progress past basis resolution and still
Expand Down
23 changes: 19 additions & 4 deletions crates/warp-core/src/optic_artifact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@ pub struct OpticInvocation {
}

const OPTIC_BASIS_RESOLUTION_V0_FIXTURE_BYTES: &[u8] = b"basis-request:resolved-fixture:v0";
const OPTIC_APERTURE_RESOLUTION_V0_FIXTURE_BYTES: &[u8] = b"aperture-request:resolved-fixture:v0";

/// Admission obstruction for an optic invocation.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
Expand All @@ -615,10 +616,11 @@ pub enum OpticInvocationObstruction {
/// outside the narrow deterministic BasisResolution v0 fixture.
UnsupportedBasisResolution,
/// The invocation reached aperture resolution after BasisResolution v0, but
/// Echo has no aperture resolver wired into admission in this slice.
/// the requested aperture shape is outside the narrow deterministic
/// ApertureResolution v0 fixture.
UnsupportedApertureResolution,
/// The invocation reached budget resolution, but Echo has no budget
/// evaluator wired into admission in this slice.
/// The invocation reached budget resolution after ApertureResolution v0,
/// but Echo has no budget evaluator wired into admission in this slice.
UnsupportedBudgetResolution,
/// Echo cannot prove that this runtime supports the registered artifact
/// requirements in this slice.
Expand Down Expand Up @@ -1186,7 +1188,10 @@ impl OpticArtifactRegistry {
CapabilityGrantValidationOutcome::IdentityCovered(_)
) {
final_obstruction = Self::resolve_basis_v0(&invocation.basis_request)
.unwrap_or(OpticInvocationObstruction::UnsupportedApertureResolution);
.unwrap_or_else(|| {
Self::resolve_aperture_v0(&invocation.aperture_request)
.unwrap_or(OpticInvocationObstruction::UnsupportedBudgetResolution)
});
}
}

Expand All @@ -1211,6 +1216,16 @@ impl OpticArtifactRegistry {
Some(OpticInvocationObstruction::UnsupportedBasisResolution)
}

fn resolve_aperture_v0(
aperture_request: &OpticApertureRequest,
) -> Option<OpticInvocationObstruction> {
if aperture_request.bytes == OPTIC_APERTURE_RESOLUTION_V0_FIXTURE_BYTES {
return None;
}

Some(OpticInvocationObstruction::UnsupportedApertureResolution)
}

fn classify_aperture_request(
aperture_request: &OpticApertureRequest,
) -> Option<OpticInvocationObstruction> {
Expand Down
89 changes: 89 additions & 0 deletions crates/warp-core/tests/optic_invocation_admission_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,17 @@ fn fixture_invocation_with_resolved_basis_and_presentation(
invocation
}

fn fixture_invocation_with_resolved_basis_aperture_and_presentation(
handle: OpticArtifactHandle,
grant_id: &str,
) -> OpticInvocation {
let mut invocation = fixture_invocation_with_resolved_basis_and_presentation(handle, grant_id);
invocation.aperture_request = OpticApertureRequest {
bytes: b"aperture-request:resolved-fixture:v0".to_vec(),
};
invocation
}

fn expected_obstructed_posture(
invocation: &OpticInvocation,
obstruction: OpticInvocationObstruction,
Expand Down Expand Up @@ -856,6 +867,84 @@ fn resolved_basis_still_obstructs_before_aperture_resolution() -> Result<(), Str
Ok(())
}

#[test]
fn unsupported_aperture_still_stops_at_unsupported_aperture_resolution() -> Result<(), String> {
let (mut registry, handle) = fixture_registry_and_handle()?;
let invocation =
fixture_invocation_with_resolved_basis_and_presentation(handle, "grant:covered");
let mut gate = fixture_gate_with_grant(fixture_grant("grant:covered"));

let outcome = registry.admit_optic_invocation_with_capability_validator(&invocation, &mut gate);

assert_eq!(
obstruction_for(&outcome),
OpticInvocationObstruction::UnsupportedApertureResolution
);
assert!(matches!(
latest_invocation_obstruction_fact(&registry)?,
GraphFact::OpticInvocationObstructed {
aperture_request_digest,
obstruction,
..
} if *aperture_request_digest == digest_invocation_request_bytes(
b"echo.optic-invocation.aperture-request.v0",
b"aperture-request:fixture"
)
&& *obstruction == InvocationObstructionKind::UnsupportedApertureResolution
));
Ok(())
}

#[test]
fn aperture_resolution_is_unreachable_when_basis_resolution_fails() -> Result<(), String> {
let (mut registry, handle) = fixture_registry_and_handle()?;
let mut invocation = fixture_invocation_with_presentation(handle, "grant:covered");
invocation.aperture_request = OpticApertureRequest {
bytes: b"aperture-request:resolved-fixture:v0".to_vec(),
};
let mut gate = fixture_gate_with_grant(fixture_grant("grant:covered"));

let outcome = registry.admit_optic_invocation_with_capability_validator(&invocation, &mut gate);

assert_eq!(
obstruction_for(&outcome),
OpticInvocationObstruction::UnsupportedBasisResolution
);
assert_ne!(
obstruction_for(&outcome),
OpticInvocationObstruction::UnsupportedApertureResolution
);
Ok(())
}

#[test]
fn resolved_aperture_still_obstructs_before_budget_resolution() -> Result<(), String> {
let (mut registry, handle) = fixture_registry_and_handle()?;
let invocation =
fixture_invocation_with_resolved_basis_aperture_and_presentation(handle, "grant:covered");
let mut gate = fixture_gate_with_grant(fixture_grant("grant:covered"));

let outcome = registry.admit_optic_invocation_with_capability_validator(&invocation, &mut gate);

assert_eq!(
obstruction_for(&outcome),
OpticInvocationObstruction::UnsupportedBudgetResolution
);
assert!(matches!(
latest_invocation_obstruction_fact(&registry)?,
GraphFact::OpticInvocationObstructed {
aperture_request_digest,
obstruction,
..
} if *aperture_request_digest == digest_invocation_request_bytes(
b"echo.optic-invocation.aperture-request.v0",
b"aperture-request:resolved-fixture:v0"
)
&& *obstruction == InvocationObstructionKind::UnsupportedBudgetResolution
));
Ok(())
}

#[test]
fn invocation_obstruction_fact_is_not_counterfactual_candidate() -> Result<(), String> {
let (mut registry, handle) = fixture_registry_and_handle()?;
Expand Down
55 changes: 38 additions & 17 deletions docs/design/optic-admission-ladder-checkpoint.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,24 @@

# Optic Admission Ladder Checkpoint

Status: BasisResolution v0 boundary checkpoint.
Scope: refusal ladder with one narrow controlled basis-resolution fixture.
Status: ApertureResolution v0 boundary checkpoint.
Scope: refusal ladder with narrow controlled basis and aperture fixtures.

## Doctrine

This checkpoint records the optic invocation admission ladder at the first
controlled basis-resolution boundary.
controlled aperture-resolution boundary.

Echo can now explain why an optic invocation is refused, but it cannot yet admit
one. There is no successful admission path in this checkpoint.

A registered artifact handle is not authority. A capability presentation slot is
not a validated grant. A basis request is not a resolved basis unless it matches
the narrow deterministic BasisResolution v0 fixture. A resolved basis is not
permission to act. An aperture request is not a resolved scope. A budget request
is not spendable runtime capacity.
permission to act. An aperture request is not a resolved scope unless it matches
the narrow deterministic ApertureResolution v0 fixture after basis resolution.
A resolved aperture is not permission to act. A budget request is not spendable
runtime capacity.

Refusal is causal evidence. Refusal is not admission, not execution, not a law
witness, and not a counterfactual candidate.
Expand All @@ -37,13 +39,17 @@ The current optic invocation admission path evaluates checks in this order:
8. Optionally publish grant-validation obstruction evidence.
9. If capability validation returns identity-covered material, resolve the
narrow BasisResolution v0 fixture or obstruct unsupported basis material.
10. If that basis fixture resolves, obstruct before aperture resolution.
11. Publish the invocation obstruction fact.
10. If that basis fixture resolves, resolve the narrow ApertureResolution v0
fixture or obstruct unsupported aperture material.
11. If that aperture fixture resolves, obstruct before budget resolution.
12. Publish the invocation obstruction fact.

Presence checks come before resolution checks. Basis resolution gates aperture
resolution. Aperture resolution gates budget evaluation and runtime support
checks. BasisResolution v0 accepts exactly one deterministic fixture shape:
`basis-request:resolved-fixture:v0`.
ApertureResolution v0 accepts exactly one deterministic fixture shape:
`aperture-request:resolved-fixture:v0`.

## Obstruction reachability

Expand All @@ -59,17 +65,21 @@ checks. BasisResolution v0 accepts exactly one deterministic fixture shape:
| `UnboundCapabilityPresentation` | Reachable today | Capability presentation material is structurally usable but not bound to the invocation. |
| `CapabilityValidationUnavailable` | Reachable today | A bound presentation exists, but no successful validation or admission has occurred yet. |
| `UnsupportedBasisResolution` | Reachable today | Identity-covered material reaches the basis boundary, but the basis shape is outside BasisResolution v0. |
| `UnsupportedApertureResolution` | Reachable today | BasisResolution v0 succeeded, but aperture resolution does not exist yet. |
| `UnsupportedBudgetResolution` | Future vocabulary | Must remain unreachable until lawful basis and aperture resolution exist. |
| `UnsupportedApertureResolution` | Reachable today | BasisResolution v0 succeeded, but the aperture shape is outside ApertureResolution v0. |
| `UnsupportedBudgetResolution` | Reachable today | ApertureResolution v0 succeeded, but budget evaluation does not exist yet. |
| `RuntimeSupportUnavailable` | Future vocabulary | Must remain unreachable until lawful basis, aperture, and budget resolution exist. |

`UnsupportedBudgetResolution` and `RuntimeSupportUnavailable` are deliberately
defined but not lawfully reachable at this checkpoint.
`RuntimeSupportUnavailable` is deliberately defined but not lawfully reachable
at this checkpoint.

`UnsupportedApertureResolution` is reachable only after the exact
BasisResolution v0 fixture resolves. For identity-covered material, unsupported
basis shapes must still stop at `UnsupportedBasisResolution`.

`UnsupportedBudgetResolution` is reachable only after the exact
ApertureResolution v0 fixture resolves. Unsupported aperture shapes must still
stop at `UnsupportedApertureResolution`.

## Non-behavior

This checkpoint does not introduce:
Expand All @@ -85,7 +95,6 @@ This checkpoint does not introduce:
- authority success
- runtime support enforcement
- budget reservation
- aperture resolution

The system remains obstruction-first. It records refusal; it does not authorize
work.
Expand All @@ -103,22 +112,34 @@ Resolving that fixture establishes only the causal state under evaluation. It
does not create authority, admission, aperture scope, budget capacity, runtime
support, scheduler work, or execution.

## ApertureResolution v0

ApertureResolution v0 is not general aperture resolution. It recognizes exactly
one deterministic fixture shape:

```text
aperture-request:resolved-fixture:v0
```

Resolving that fixture establishes only the bounded observation/action window
inside a resolved basis. It does not create authority, admission, budget
capacity, runtime support, scheduler work, or execution.

## Next transition point

The next transition point is ApertureResolution v0.
The next transition point is BudgetResolution v0.

That transition must be narrow and explicit. It must not imply successful
admission, budget spendability, runtime support, execution, or authority
validation.

## Tripwire

If a future slice makes `UnsupportedBudgetResolution` or
`RuntimeSupportUnavailable` reachable before a lawful aperture resolution
boundary exists, the admission ladder is wrong.
If a future slice makes `RuntimeSupportUnavailable` reachable before a lawful
budget resolution boundary exists, the admission ladder is wrong.

If a future slice introduces a successful admission path before a resolved basis,
resolved aperture, evaluated budget, runtime support check, and validated grant
exist, the admission ladder is wrong.

BasisResolution v0 is controlled resolved state, not admission.
ApertureResolution v0 is controlled resolved state, not admission.
Loading