chio-kernel-mobile 0.1.2

Mobile FFI bindings (iOS / Android) for the portable Chio kernel core via UniFFI
Documentation
// UDL interface for chio-kernel-mobile.
//
// This file is the single source of truth for the Swift + Kotlin
// bindings emitted by `uniffi-bindgen`. Every exported symbol below
// maps 1:1 onto a `pub fn` in `src/lib.rs` with the same name; the
// build-script-generated scaffolding (see `build.rs`) wires them
// together at compile time.
//
// Design notes:
//
//  - Every public entry point is JSON-in / JSON-out. Mobile callers
//    serialize a Chio type (CapabilityToken, PortableToolCallRequest,
//    ChioReceiptBody, PortablePassportEnvelope) to JSON using the
//    host-side Chio SDK, hand the string to us, and receive a JSON
//    string back. This keeps the UDL surface small and avoids having
//    to restate the 40+ field ChioScope graph in IDL.
//
//  - Errors are a flat enum with String payloads so Swift
//    (`ChioMobileError`) and Kotlin (`ChioMobileException`) both render
//    human-readable deny reasons via `.message` / `.localizedMessage`.
//
//  - `VerifiedCapability` and `PortablePassportMetadata` are returned
//    as UDL records so the mobile app can inspect the decoded view
//    (subject, issuer, expiry, evaluated_at) without re-parsing the
//    wrapped JSON.

namespace chio_kernel_mobile {
    // Evaluate a tool-call request against a capability token.
    //
    // `request_json` must be a JSON object of the shape:
    //   {
    //     "capability": <CapabilityToken JSON>,
    //     "trusted_issuers": [<PublicKey hex>, ...],
    //     "request": <PortableToolCallRequest JSON>,
    //     "now_secs": <optional Unix seconds; defaults to MobileClock>
    //   }
    //
    // Returns a JSON object with the verdict:
    //   {
    //     "verdict": "allow" | "deny",
    //     "reason": <string, present on deny>,
    //     "matched_grant_index": <int, present on allow>
    //   }
    [Throws=ChioMobileError]
    string evaluate(string request_json);

    // Sign a receipt body with the given Ed25519 signing seed
    // (PUBLIC WYSIWYS signer; fail-closed).
    //
    // `body_json` is the canonical JSON of a ChioReceiptBody. The
    // receipt body MUST set `kernel_key` to the public key that
    // corresponds to `signing_seed_hex`; otherwise the signing pipeline
    // fails fast with ChioMobileError.KernelKeyMismatch.
    //
    // `canonical_content_hex` is the lowercase-hex encoding of
    // the exact byte preimage `content_hash` was derived from. The signer
    // recomputes the hash inside the trust boundary and refuses to sign on
    // mismatch (ChioMobileError.SigningFailed), closing render-A / sign-B.
    // This signer does NOT relay a trusted body; callers that only forward
    // an upstream-minted body must use sign_receipt_relaying_trusted_body.
    //
    // `signing_seed_hex` is a 32-byte Ed25519 seed, lowercase hex,
    // with optional `0x` prefix.
    //
    // Returns the signed ChioReceipt as JSON, ready to be queued for
    // upload to the operator's receipt-log sink when connectivity
    // returns (see bindings/README.md for the offline-sync pattern).
    [Throws=ChioMobileError]
    string sign_receipt(string body_json, string canonical_content_hex, string signing_seed_hex);

    // Relay-sign an already-minted, upstream-trusted receipt body
    // Trusted-body relay seam. NOT the default public signer.
    //
    // Trusts the caller-supplied `content_hash` and does NOT recompute it.
    // Use only to forward a body an upstream trusted producer already minted
    // (where the WYSIWYS recompute already ran). Content-bearing callers MUST
    // use sign_receipt instead so the recompute gate runs.
    [Throws=ChioMobileError]
    string sign_receipt_relaying_trusted_body(string body_json, string signing_seed_hex);

    // Verify a capability token against a trusted-issuer key.
    //
    // Returns the verified snapshot (subject, issuer, scope summary,
    // validity window, evaluation time). Signature, issuer-trust, and
    // time-bound failures surface as ChioMobileError.InvalidCapability.
    [Throws=ChioMobileError]
    VerifiedCapability verify_capability(string token_json, string authority_pub_hex);

    // Verify a capability token with the full portable JSON context.
    //
    // `request_json` accepts the same trust-root and parent-budget
    // snapshot fields as `evaluate`, allowing delegated tokens to seed
    // sibling-sum enforcement before verification.
    [Throws=ChioMobileError]
    VerifiedCapability verify_capability_with_context(string request_json);

    // Verify a portable passport envelope (v1 wire format).
    //
    // `envelope_json` is the JSON-encoded PortablePassportEnvelope.
    // `issuer_pub_hex` is the trusted authority public key in lowercase hex.
    // `now_secs` is the Unix timestamp (signed 64-bit) to evaluate the
    // validity window against. A value <= 0 falls back to MobileClock.
    //
    // Returns a metadata record summarising the verified envelope.
    [Throws=ChioMobileError]
    PortablePassportMetadata verify_passport(
        string envelope_json,
        string issuer_pub_hex,
        i64 now_secs
    );

    // Produce an App Attest challenge envelope bound to a server challenge.
    //
    // The iOS host app obtains the platform attestation object through
    // DeviceCheck and sends it to verify_app_attest_evidence.
    [Throws=ChioMobileError]
    string attest_app_attest(string key_id, string challenge_hex);

    // Verify an Apple App Attest attestation object.
    //
    // `previous_counter` is optional by convention: pass -1 when no prior
    // counter exists, otherwise pass the last accepted counter. The verifier
    // rejects same-or-lower counters fail-closed.
    [Throws=ChioMobileError]
    string verify_app_attest_evidence(
        string key_id,
        string challenge_hex,
        string app_id,
        string attestation_cbor_hex,
        i64 previous_counter
    );

    // Produce a Play Integrity challenge envelope bound to an issuer nonce.
    //
    // The Android host app obtains the platform JWS through Play Integrity
    // and sends it to verify_play_integrity_evidence.
    [Throws=ChioMobileError]
    string attest_play_integrity(string nonce_hex);

    // Verify a Play Integrity JWS against an issuer nonce and JWKS.
    [Throws=ChioMobileError]
    string verify_play_integrity_evidence(
        string token,
        string expected_nonce,
        string expected_package_name,
        string expected_audience,
        string jwks_json
    );

    // Shape-check a mobile receipt against App Attest or Play Integrity evidence.
    //
    // Returns an explicit non-authoritative status until full receipt-chain
    // verification is wired to trusted issuer pins and challenge binding.
    [Throws=ChioMobileError]
    string verify_mobile_receipt(string receipt_json, string evidence_json);
};

// Verified capability snapshot returned by `verify_capability`.
//
// Mirrors `chio_kernel_core::VerifiedCapability` minus the `scope` field,
// which is returned as its canonical JSON blob so the mobile host can
// decode it using whatever projection it prefers.
dictionary VerifiedCapability {
    string id;
    string subject_hex;
    string issuer_hex;
    string scope_json;
    u64 issued_at;
    u64 expires_at;
    u64 evaluated_at;
};

// Verified portable-passport metadata returned by `verify_passport`.
//
// Mirrors `chio_kernel_core::VerifiedPassport` minus the payload byte
// blob; the payload is returned as lowercase hex so Swift/Kotlin can
// surface it as a `Data` / `ByteArray` after one `.hexDecode()`.
dictionary PortablePassportMetadata {
    string subject;
    string issuer_hex;
    u64 issued_at;
    u64 expires_at;
    u64 evaluated_at;
    string payload_canonical_hex;
};

// Error surface for the FFI.
//
// Each variant carries a human-readable `message` string. Swift sees
// this as `ChioMobileError.invalidCapability(message: String)`; Kotlin
// sees it as `ChioMobileException.InvalidCapability(val message: String)`.
// The message is the portable-core `deny_reason()` output or the JSON
// parse error at the FFI boundary.
[Error]
interface ChioMobileError {
    InvalidJson(string message);
    InvalidHex(string message);
    WeakEntropy(string message);
    InvalidCapability(string message);
    InvalidPassport(string message);
    AttestationUnavailable(string message);
    AttestationRejected(string message);
    KernelKeyMismatch(string message);
    SigningFailed(string message);
    EvaluationDenied(string message);
    Internal(string message);
};