a3s-use-core 0.2.3

Shared typed contracts for A3S Use domains
Documentation
use a3s_use_core::{
    CatalogSurface, OkfBundleContract, PlanPackageChangeKind, PlannedPackageTransition,
    PluginOperationPlan, PluginOperationPlanBinding, PluginOperationPlanDraft,
    PluginPermissionCeiling, PluginPlanSource, PluginSurfaceKind,
    PLUGIN_OPERATION_PLAN_DRAFT_SCHEMA_V3, PLUGIN_OPERATION_PLAN_SCHEMA_V4,
    PLUGIN_PERMISSION_SCHEMA,
};

const INSTALL_PLAN: &[u8] = include_bytes!("../fixtures/plugins/operation-plan-install-v4.json");
const OKF_INSTALL_PLAN: &[u8] =
    include_bytes!("../fixtures/plugins/operation-plan-install-okf-v4.json");
const OKF_INSTALL_PLAN_DIGEST: &str =
    include_str!("../fixtures/plugins/operation-plan-install-okf-v4.sha256").trim_ascii_end();

fn canonical_fixture(bytes: &[u8]) -> &[u8] {
    bytes.strip_suffix(b"\n").unwrap_or(bytes)
}

fn install_plan() -> PluginOperationPlan {
    PluginOperationPlan::from_json(INSTALL_PLAN).unwrap()
}

fn okf_install_plan() -> PluginOperationPlan {
    let expected = install_plan();
    let mut after = expected.packages[0].after.clone().unwrap();
    let bundle =
        OkfBundleContract::from_json(include_bytes!("../fixtures/okf/bundle-contract-v1.json"))
            .unwrap();
    after.release.package_id = "acme/knowledge".to_owned();
    after.release.version = "1.0.0".to_owned();
    after.release.package_sha256 =
        "sha256:e030e6e8c3afa6383536b4973395e12b05257d2b7b10bf042f3bfaf71b420fe2".to_owned();
    after.release.manifest_sha256 =
        "sha256:16d065341edebaf45e0d633e46614155a60b853738290bbac8c5b62d9230bce2".to_owned();
    after.release.surfaces = vec![CatalogSurface {
        kind: PluginSurfaceKind::Okf,
        id: "domain-knowledge".to_owned(),
        optional: false,
        workload: None,
        mcp_transport: None,
        mcp_tool_count: None,
        okf_bundle: Some(bundle),
        requires: Vec::new(),
    }];
    after.permissions = PluginPermissionCeiling {
        schema: PLUGIN_PERMISSION_SCHEMA.to_owned(),
        surfaces: Vec::new(),
    };
    after.release.permission_ceiling_digest = after.permissions.descriptor_digest().unwrap();
    let package_digest = after.release.package_sha256.clone();
    let transition =
        PlannedPackageTransition::resolved(
            "acme/knowledge",
            expected.packages[0].role,
            PlanPackageChangeKind::Add,
            None,
            Some(after),
            Some(PluginPlanSource::ReleaseBundle {
                bundle_digest:
                    "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
                        .to_owned(),
                package_digest,
            }),
        )
        .unwrap();
    let mut impact = expected.impact;
    impact.download_bytes = 3_366;
    impact.installed_bytes_after = 3_366;
    let draft = PluginOperationPlanDraft::new(
        expected.action,
        "acme/knowledge",
        "knowledge:local",
        vec![transition],
        Vec::new(),
        expected.workspace_impacts,
        impact,
        expected.state,
    )
    .unwrap();
    assert_eq!(draft.schema, PLUGIN_OPERATION_PLAN_DRAFT_SCHEMA_V3);
    draft
        .bind(PluginOperationPlanBinding {
            operation_id: "install:acme-knowledge:0001".to_owned(),
            created_at_ms: expected.created_at_ms,
            expires_at_ms: expected.expires_at_ms,
            scope: expected.scope,
            authority: expected.authority,
        })
        .unwrap()
}

#[test]
fn draft_omits_host_identity_scope_and_authority_then_binds_exactly() {
    let expected = install_plan();
    let draft = PluginOperationPlanDraft::new(
        expected.action,
        expected.package_id.clone(),
        expected.component_id.clone(),
        expected.packages.clone(),
        expected.providers.clone(),
        expected.workspace_impacts.clone(),
        expected.impact.clone(),
        expected.state.clone(),
    )
    .unwrap();
    let value = serde_json::to_value(&draft).unwrap();

    assert!(value.get("operationId").is_none());
    assert!(value.get("createdAtMs").is_none());
    assert!(value.get("expiresAtMs").is_none());
    assert!(value.get("scope").is_none());
    assert!(value.get("authority").is_none());
    assert!(value.get("secretChanges").is_none());

    let bound = draft
        .bind(PluginOperationPlanBinding {
            operation_id: expected.operation_id.clone(),
            created_at_ms: expected.created_at_ms,
            expires_at_ms: expected.expires_at_ms,
            scope: expected.scope.clone(),
            authority: expected.authority.clone(),
        })
        .unwrap();

    assert_eq!(bound, expected);
}

#[test]
fn draft_json_rejects_delegated_host_authority() {
    let expected = install_plan();
    let draft = PluginOperationPlanDraft::new(
        expected.action,
        expected.package_id,
        expected.component_id,
        expected.packages,
        expected.providers,
        expected.workspace_impacts,
        expected.impact,
        expected.state,
    )
    .unwrap();
    let mut value = serde_json::to_value(draft).unwrap();
    value["authority"] = serde_json::json!({
        "actor": "agent",
        "decision": "allow",
        "policyDigest": format!("sha256:{}", "a".repeat(64)),
        "confirmationRequired": false,
    });

    assert!(PluginOperationPlanDraft::from_json(&serde_json::to_vec(&value).unwrap()).is_err());
}

#[test]
fn resolved_transition_derives_the_exact_surface_delta() {
    let expected = install_plan().packages.remove(0);
    let resolved = PlannedPackageTransition::resolved(
        expected.package_id.clone(),
        expected.role,
        PlanPackageChangeKind::Add,
        None,
        expected.after.clone(),
        expected.source.clone(),
    )
    .unwrap();

    assert_eq!(resolved, expected);
}

#[test]
fn resolved_retained_dependency_has_no_surface_delta() {
    let package = install_plan().packages.remove(0);
    let package_id = package.package_id;
    let state = package.after.unwrap();
    let resolved = PlannedPackageTransition::resolved(
        package_id,
        a3s_use_core::PlanPackageRole::Dependency,
        PlanPackageChangeKind::Retain,
        Some(state.clone()),
        Some(state),
        None,
    )
    .unwrap();

    assert!(resolved.surfaces.is_empty());
}

#[test]
fn draft_rejects_missing_explicit_runtime_provider_evidence() {
    let expected = install_plan();
    let result = PluginOperationPlanDraft::new(
        expected.action,
        expected.package_id,
        expected.component_id,
        expected.packages,
        Vec::new(),
        expected.workspace_impacts,
        expected.impact,
        expected.state,
    );

    assert!(result.is_err());
}

#[test]
fn unbound_draft_validates_planner_evidence_but_cannot_be_bound() {
    let expected = install_plan();
    let mut draft = PluginOperationPlanDraft::new_unbound(
        expected.action,
        expected.package_id.clone(),
        expected.component_id.clone(),
        expected.packages.clone(),
        expected.workspace_impacts.clone(),
        expected.impact.clone(),
        expected.state.clone(),
    )
    .unwrap();
    let bytes = serde_json::to_vec(&draft).unwrap();
    assert_eq!(
        PluginOperationPlanDraft::from_unbound_json(&bytes).unwrap(),
        draft
    );
    assert!(draft
        .clone()
        .bind(PluginOperationPlanBinding {
            operation_id: expected.operation_id.clone(),
            created_at_ms: expected.created_at_ms,
            expires_at_ms: expected.expires_at_ms,
            scope: expected.scope.clone(),
            authority: expected.authority.clone(),
        })
        .is_err());

    draft.providers = expected.providers.clone();
    draft.validate().unwrap();
    assert_eq!(
        draft
            .bind(PluginOperationPlanBinding {
                operation_id: expected.operation_id.clone(),
                created_at_ms: expected.created_at_ms,
                expires_at_ms: expected.expires_at_ms,
                scope: expected.scope.clone(),
                authority: expected.authority.clone(),
            })
            .unwrap(),
        expected
    );
}

#[test]
fn okf_draft_derives_exact_bundle_impact_without_a_runtime_provider() {
    let mut plan = okf_install_plan();
    assert_eq!(plan.schema, PLUGIN_OPERATION_PLAN_SCHEMA_V4);
    assert_eq!(plan.impact.okf_changes.len(), 1);
    assert_eq!(
        plan.impact.okf_changes[0]
            .after
            .as_ref()
            .unwrap()
            .content_digest,
        "sha256:bd85b0b63adb32bdf616384a619286af4c32401542655dd09e00450902ab478d"
    );
    assert!(plan.providers.is_empty());
    plan.validate().unwrap();
    assert_eq!(
        plan.canonical_bytes().unwrap(),
        canonical_fixture(OKF_INSTALL_PLAN)
    );
    assert_eq!(plan.descriptor_digest().unwrap(), OKF_INSTALL_PLAN_DIGEST);
    assert_eq!(
        PluginOperationPlan::from_json(OKF_INSTALL_PLAN).unwrap(),
        plan
    );

    plan.schema = "a3s.use.plugin-operation-plan.v3".to_owned();
    assert!(plan.validate().is_err());
}