You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maka.apache.org by wy...@apache.org on 2026/10/20 08:32:40 UTC

(maka) branch rust-preview updated: fix: preserve complete service values and operation receipts

This is an automated email from the ASF dual-hosted git repository.

M4n5ter pushed a commit to branch rust-preview
in repository https://gitbox.apache.org/repos/asf/maka.git


The following commit(s) were added to refs/heads/rust-preview by this push:
     new c342c48877 fix: preserve complete service values and operation receipts
c342c48877 is described below

commit c342c48877ae3e9ea632091f23c67640791d639f
Author: Wang <m4...@gmail.com>
AuthorDate: Tue Oct 20 16:32:32 2026 +0800

    fix: preserve complete service values and operation receipts
    
    Remove redundant JSON size quotas from Host and JavaScript calls, callback
    arguments, configuration and durable operation requests/results. Keep actual
    input reservations, exact-number delivery, original identity and cleanup.
    
    Verify complete Unicode values through native and nested JavaScript calls,
    original mutation retry/recovery and reopened journals; remove obsolete
    quota-refusal assertions while retaining authority and precision coverage.
    
    Generated-by: Codex
---
 platform/event-log/README.md                       |   2 +
 platform/event-log/README.zh-CN.md                 |   2 +
 platform/event-log/src/applications/intents.rs     |  13 +-
 .../event-log/src/applications/intents/tests.rs    |   4 +-
 platform/event-log/src/applications/operations.rs  |  56 ++++----
 .../event-log/src/applications/operations/tests.rs | 120 +++++++++++-------
 platform/host-js/tests/application_services.rs     | 141 ++++++++++++++++++++-
 .../tests/application_services/operations.rs       |  44 +++++--
 .../host-js/tests/application_services/receipts.rs |  23 ++--
 platform/host-runtime/README.md                    |   4 +-
 platform/host-runtime/README.zh-CN.md              |   4 +-
 platform/host-runtime/src/application.rs           |  14 +-
 .../host-runtime/src/application/operations.rs     |   4 +-
 platform/host-runtime/src/application/owner.rs     |  10 +-
 platform/host-runtime/src/application/requests.rs  |   1 -
 .../src/application/resource_ingress.rs            |  12 +-
 platform/js-runtime/src/plugin/captured.rs         |  12 +-
 platform/js-runtime/src/plugin/request.rs          |  11 +-
 .../tests/integration/plugin_vm/captured.rs        |   5 +-
 .../tests/integration/plugin_vm/request.rs         |   6 +-
 platform/ui-runtime/src/actions/mutations.rs       |   3 +-
 21 files changed, 336 insertions(+), 155 deletions(-)

diff --git a/platform/event-log/README.md b/platform/event-log/README.md
index d61b7fb752..bab769feab 100644
--- a/platform/event-log/README.md
+++ b/platform/event-log/README.md
@@ -25,6 +25,8 @@ Owns the SQLite event store and State Root lease. It persists application source
 
 Original operation contracts are stored once by digest. Operation requests and receipt references carry that identity, so journal reads, caller history and UI delivery do not repeatedly copy service schemas. Reads verify the exact original request fingerprint; admission still validates the complete contract and resource requirements.
 
+The operation journal retains complete admitted requests and returned values without separate request, result or receipt-reference size quotas. Exact retries and reopened readers recover the original outcome and cleanup status.
+
 Message delivery retains prepared content, the editable original and the original submission digest. Its internal records can exceed the public request envelope because they preserve these separate facts; writes and exact message reads do not reapply that envelope to the encoded record. Pending queues have no fixed message-count or aggregate-byte quota. Stop and whole-queue retraction retain complete admitted entries in their transactional receipts, without a separate receipt-size quota. [...]
 
 Source messages, executor tool calls and generated tool results share the Session's visible-message identity namespace. Admission checks both claim orders against canonical facts, including results synthesized for pending tools at executor completion or invocation termination. Only actual result identities are occupied; a matching suffix alone does not reserve an identity.
diff --git a/platform/event-log/README.zh-CN.md b/platform/event-log/README.zh-CN.md
index 72abaa24e0..0cceda3aaa 100644
--- a/platform/event-log/README.zh-CN.md
+++ b/platform/event-log/README.zh-CN.md
@@ -25,6 +25,8 @@
 
 原始操作契约按摘要只存储一次。操作请求和回执引用只携带该身份,日志读取、调用方历史与 UI 传递不再逐次复制服务 schema。读取仍核对原始请求指纹,执行准入仍校验完整契约和资源要求。
 
+操作日志完整保存已受理的请求和返回值,不另设请求、结果或回执引用的大小额度。精确重试和重开后的读取恢复原始结果与清理状态。
+
 消息交付保留准备后的内容、可编辑原文和最初提交的摘要。内部记录保存这些不同事实,编码后可能大于公开请求;写入与精确消息读取不再对整条编码记录重复套用请求大小限制。待处理队列不设固定条数或总字节额度。停止和整队撤回在同一事务的回执中保留完整获准条目,不另设回执大小额度。精确重试和重开后的读取返回同一份原始回执。通过 `editable_message` 按 Session、Turn 和消息身份读取一条已拥有的来源。
 
 来源消息、执行器工具调用与生成的工具结果共享 Session 的可见消息身份空间。无论哪一方先声明,准入都依据规范事实检查冲突,包括执行器完成或调用终止时为待完成工具补出的结果。只有实际结果身份被占用;仅后缀相同不会预留身份。
diff --git a/platform/event-log/src/applications/intents.rs b/platform/event-log/src/applications/intents.rs
index b27eafdebe..9b71d9908d 100644
--- a/platform/event-log/src/applications/intents.rs
+++ b/platform/event-log/src/applications/intents.rs
@@ -28,7 +28,6 @@ use sqlx::{Connection, Row, SqliteConnection};
 use std::sync::Arc;
 use uuid::Uuid;
 
-const MAX_REFERENCE: usize = 512 * 1024;
 const MAX_PAGE: usize = 1024 * 1024;
 const MAX_RECOVERY: usize = 32 * 1024;
 
@@ -81,7 +80,6 @@ impl CallerConfirmation {
         }
         self.caller.validate().map_err(invalid)?;
         consumer_valid(&self.consumer)?;
-        encode(&self.reference, MAX_REFERENCE)?;
         encode(self, MAX_PAGE)?;
         self.reference
             .validate()
@@ -113,13 +111,11 @@ async fn read(
     consumer: &InstanceId,
     operation: Uuid,
 ) -> Result<Option<CallerIntent>, StoreError> {
-    let row = sqlx::query("SELECT cursor, source_revision, CASE WHEN length(CAST(reference_json AS BLOB)) <= 524288 THEN reference_json END AS reference_json, CASE WHEN length(CAST(recovery_json AS BLOB)) <= 32768 THEN recovery_json END AS recovery_json FROM application_intents WHERE deployment=? AND consumer=? AND operation=?")
+    let row = sqlx::query("SELECT cursor, source_revision, reference_json, CASE WHEN length(CAST(recovery_json AS BLOB)) <= 32768 THEN recovery_json END AS recovery_json FROM application_intents WHERE deployment=? AND consumer=? AND operation=?")
         .bind(deployment.to_string()).bind(encode(consumer,4096)?).bind(operation.to_string()).fetch_optional(connection).await?;
     row.map(|row| {
-        let reference: RecoveryRef = serde_json::from_str(
-            &row.try_get::<Option<String>, _>("reference_json")?
-                .ok_or_else(|| invalid("caller reference exceeds 512 KiB"))?,
-        )?;
+        let reference: RecoveryRef =
+            serde_json::from_str(&row.try_get::<String, _>("reference_json")?)?;
         let recovery = serde_json::from_str(
             &row.try_get::<Option<String>, _>("recovery_json")?
                 .ok_or_else(|| invalid("caller recovery metadata exceeds 32 KiB"))?,
@@ -182,7 +178,6 @@ impl EventLog {
     ) -> Result<RecordedIntent, StoreError> {
         consumer_valid(&consumer)?;
         reference.validate().map_err(|e| invalid(e.to_string()))?;
-        encode(&reference, MAX_REFERENCE)?;
         encode(&recovery, MAX_RECOVERY)?;
         let loaded = self
             .load_application_at(&caller)
@@ -205,7 +200,7 @@ impl EventLog {
         source.check(self, &consumer)?;
         let caller = source.reference().clone();
         reference.validate().map_err(|e| invalid(e.to_string()))?;
-        let encoded = encode(&reference, MAX_REFERENCE)?;
+        let encoded = serde_json::to_string(&reference)?;
         let encoded_recovery = encode(&recovery, MAX_RECOVERY)?;
         let domain = self.application_domain()?;
         let owner = self.root_owner.as_ref().expect("owned caller Root").clone();
diff --git a/platform/event-log/src/applications/intents/tests.rs b/platform/event-log/src/applications/intents/tests.rs
index 5c179e6154..c30248988a 100644
--- a/platform/event-log/src/applications/intents/tests.rs
+++ b/platform/event-log/src/applications/intents/tests.rs
@@ -295,7 +295,7 @@ async fn caller_requires_owned_exact_source_and_actual_executable_namespace() {
 }
 
 #[tokio::test]
-async fn corrupted_history_is_bounded_and_never_overwritten_as_a_fresh_intent() {
+async fn corrupted_history_is_never_overwritten_as_a_fresh_intent() {
     let (_dir, store) = store().await;
     let deployment = Uuid::new_v4();
     let caller = source(&store, deployment, 0).await;
@@ -341,7 +341,7 @@ async fn corrupted_history_is_bounded_and_never_overwritten_as_a_fresh_intent()
                     "UPDATE application_intents SET operation=?, reference_json=? WHERE cursor=?",
                 )
                 .bind(operation)
-                .bind(serde_json::to_string(&"x".repeat(MAX_REFERENCE)).unwrap())
+                .bind("{}")
                 .bind(cursor as i64)
                 .execute(&mut *connection)
                 .await?;
diff --git a/platform/event-log/src/applications/operations.rs b/platform/event-log/src/applications/operations.rs
index ff6dcb8868..7bdfd7da41 100644
--- a/platform/event-log/src/applications/operations.rs
+++ b/platform/event-log/src/applications/operations.rs
@@ -37,8 +37,6 @@ use sqlx::{Connection, Row, SqliteConnection};
 use std::sync::Arc;
 use uuid::Uuid;
 
-const MAX_REQUEST: usize = 2 * 1024 * 1024;
-const MAX_RESULT: usize = 1024 * 1024 + 128;
 const MAX_DIAGNOSTIC: usize = 64 * 1024;
 
 /// Trusted embedding supplies these facts after its private admission check.
@@ -82,7 +80,7 @@ impl OperationTemplate {
         else {
             return Ok(Default::default());
         };
-        let contract_json: Arc<str> = encode(contract, MAX_REQUEST)?.into();
+        let contract_json: Arc<str> = serde_json::to_string(contract)?.into();
         let recovery =
             RecoveryContract::for_method(contract, mutation).map_err(|e| invalid(e.to_string()))?;
         methods
@@ -103,12 +101,6 @@ impl OperationTemplate {
             .collect()
     }
     pub fn prepare(&self, request: OperationRequest<()>) -> Result<PreparedOperation, StoreError> {
-        // The unit contract serializes as null. Replacing those four bytes with
-        // the cached contract preserves the original entire-record byte budget.
-        let request_bytes = encode(&request, MAX_REQUEST)?.len();
-        if request_bytes - 4 + self.contract_json.len() > MAX_REQUEST {
-            return Err(invalid("operation request exceeds limit"));
-        }
         if request.method != self.method {
             return Err(invalid("operation template method mismatch"));
         }
@@ -167,8 +159,6 @@ impl OperationRequest {
     }
 
     fn journal(&self) -> Result<OperationRequest<RecoveryContract>, StoreError> {
-        // Bound the entire record before building a canonical representation.
-        encode(self, MAX_REQUEST)?;
         let Interface::Service { methods } = &self.contract.interface else {
             return Err(invalid("operation requires a service contract"));
         };
@@ -207,7 +197,6 @@ impl OperationRequest {
 
 impl OperationRequest<RecoveryContract> {
     fn stored_reference(&self) -> Result<RecoveryRef, StoreError> {
-        encode(self, MAX_REQUEST)?;
         if self.consumer.0.is_empty()
             || self.consumer.0.len() > 64
             || self.consumer.0.iter().any(Uuid::is_nil)
@@ -223,7 +212,9 @@ impl OperationRequest<RecoveryContract> {
         canonical.sort_all_objects();
         let fingerprint = format!(
             "sha256-{}",
-            hex::encode(Sha256::digest(encode(&canonical, MAX_REQUEST)?.as_bytes()))
+            hex::encode(Sha256::digest(
+                serde_json::to_string(&canonical)?.as_bytes()
+            ))
         );
         let reference = RecoveryRef {
             source: self.source.clone(),
@@ -277,7 +268,6 @@ fn validate_settlement(
     {
         return Err(invalid("operation diagnostic exceeds 64 KiB"));
     }
-    encode(outcome, MAX_RESULT)?;
     encode(cleanup, MAX_DIAGNOSTIC + 128)?;
     Ok(())
 }
@@ -286,21 +276,23 @@ async fn read(
     reference: &RecoveryRef,
 ) -> Result<Option<Record>, StoreError> {
     let namespace = encode(&reference.namespace, 4096)?;
-    let Some(row) = sqlx::query("SELECT source_revision, contract_digest,
-        CASE WHEN length(CAST(request_json AS BLOB)) <= 2097152 THEN request_json END AS request_json,
-        CASE WHEN length(CAST(outcome_json AS BLOB)) <= 1048704 THEN outcome_json END AS outcome_json,
+    let Some(row) = sqlx::query(
+        "SELECT source_revision, contract_digest, request_json, outcome_json,
         CASE WHEN length(CAST(cleanup_json AS BLOB)) <= 65664 THEN cleanup_json END AS cleanup_json
-        FROM application_operations WHERE deployment=? AND namespace=? AND operation=?")
-        .bind(reference.source.deployment.to_string()).bind(namespace).bind(reference.operation.to_string())
-        .fetch_optional(connection).await? else { return Ok(None); };
-    let request: OperationRequest<RecoveryContract> = serde_json::from_str(
-        &row.try_get::<Option<String>, _>("request_json")?
-            .ok_or_else(|| invalid("stored operation request exceeds limit"))?,
-    )?;
-    let outcome: OperationOutcome = serde_json::from_str(
-        &row.try_get::<Option<String>, _>("outcome_json")?
-            .ok_or_else(|| invalid("stored operation outcome exceeds limit"))?,
-    )?;
+        FROM application_operations WHERE deployment=? AND namespace=? AND operation=?",
+    )
+    .bind(reference.source.deployment.to_string())
+    .bind(namespace)
+    .bind(reference.operation.to_string())
+    .fetch_optional(connection)
+    .await?
+    else {
+        return Ok(None);
+    };
+    let request: OperationRequest<RecoveryContract> =
+        serde_json::from_str(&row.try_get::<String, _>("request_json")?)?;
+    let outcome: OperationOutcome =
+        serde_json::from_str(&row.try_get::<String, _>("outcome_json")?)?;
     let cleanup: OperationCleanup = serde_json::from_str(
         &row.try_get::<Option<String>, _>("cleanup_json")?
             .ok_or_else(|| invalid("stored operation cleanup exceeds limit"))?,
@@ -339,7 +331,7 @@ impl EventLog {
         &self,
         request: OperationRequest,
     ) -> Result<Dispatch, StoreError> {
-        let contract_json = encode(&request.contract, MAX_REQUEST)?;
+        let contract_json = serde_json::to_string(&request.contract)?;
         let request = request.journal()?;
         let reference = request.stored_reference()?;
         self.dispatch_prepared_operation(PreparedOperation {
@@ -361,7 +353,7 @@ impl EventLog {
         } = prepared;
         self.operation_domain(&reference)?;
         let owner = self.root_owner.as_ref().expect("owned Root").clone();
-        let request_json = encode(&request, MAX_REQUEST)?;
+        let request_json = serde_json::to_string(&request)?;
         let commits = self.commits.clone();
         self.connection
             .run(move |connection| {
@@ -389,7 +381,7 @@ impl EventLog {
                         .bind(reference.operation.to_string())
                         .bind(reference.source.revision as i64)
                         .bind(request_json)
-                        .bind(encode(&OperationOutcome::Unresolved, MAX_RESULT)?)
+                        .bind(serde_json::to_string(&OperationOutcome::Unresolved)?)
                         .bind(encode(
                             &OperationCleanup::Unconfirmed,
                             MAX_DIAGNOSTIC + 128,
@@ -428,7 +420,7 @@ impl EventLog {
                 if old != observation { return Err(StoreError::EventConflict); }
             } else {
                 sqlx::query("UPDATE application_operations SET outcome_json=?, cleanup_json=? WHERE deployment=? AND namespace=? AND operation=?")
-                    .bind(encode(&observation.outcome, MAX_RESULT)?).bind(encode(&observation.cleanup, MAX_DIAGNOSTIC + 128)?)
+                    .bind(serde_json::to_string(&observation.outcome)?).bind(encode(&observation.cleanup, MAX_DIAGNOSTIC + 128)?)
                     .bind(reference.source.deployment.to_string()).bind(encode(&reference.namespace, 4096)?)
                     .bind(reference.operation.to_string()).execute(&mut *tx).await?;
             }
diff --git a/platform/event-log/src/applications/operations/tests.rs b/platform/event-log/src/applications/operations/tests.rs
index 5040388a16..266b16a1b7 100644
--- a/platform/event-log/src/applications/operations/tests.rs
+++ b/platform/event-log/src/applications/operations/tests.rs
@@ -384,30 +384,25 @@ async fn dispatch_requires_original_source_and_settlement_requires_original_clai
     store.close().await.unwrap();
 }
 #[tokio::test]
-async fn stored_receipt_bounds_precede_materialization() {
-    for column in ["request_json", "outcome_json", "cleanup_json"] {
-        let (_dir, store) = store().await;
-        let original = request(&store).await;
-        let reference = original.reference().unwrap();
-        store.dispatch_operation(original).await.unwrap();
-        store.connection.run(move |conn| Box::pin(async move {
-            let sql = match column {
-                "request_json" => "UPDATE application_operations SET request_json=json_object('huge', printf('%.*c', 4194304, 'x'))",
-                "outcome_json" => "UPDATE application_operations SET outcome_json=json_object('huge', printf('%.*c', 4194304, 'x'))",
-                _ => "UPDATE application_operations SET cleanup_json=json_object('huge', printf('%.*c', 4194304, 'x'))",
-            };
-            sqlx::query(sql).execute(conn).await?; Ok(())
-        })).await.unwrap();
-        assert!(
-            store
-                .operation_observation(&reference)
-                .await
-                .unwrap_err()
-                .to_string()
-                .contains("exceeds limit")
-        );
-        store.close().await.unwrap();
-    }
+async fn stored_cleanup_bounds_precede_materialization() {
+    let (_dir, store) = store().await;
+    let original = request(&store).await;
+    let reference = original.reference().unwrap();
+    store.dispatch_operation(original).await.unwrap();
+    store.connection.run(move |conn| Box::pin(async move {
+        sqlx::query("UPDATE application_operations SET cleanup_json=json_object('huge', printf('%.*c', 4194304, 'x'))")
+            .execute(conn).await?;
+        Ok(())
+    })).await.unwrap();
+    assert!(
+        store
+            .operation_observation(&reference)
+            .await
+            .unwrap_err()
+            .to_string()
+            .contains("exceeds limit")
+    );
+    store.close().await.unwrap();
 }
 
 #[tokio::test]
@@ -631,7 +626,7 @@ fn dynamic_request(request: &OperationRequest) -> OperationRequest<()> {
 }
 
 #[tokio::test]
-async fn compiled_operation_preserves_reference_capture_budget_and_original_dispatch() {
+async fn compiled_operation_preserves_reference_capture_and_complete_original_dispatch() {
     let (_dir, store) = store().await;
     let mut original = request(&store).await;
     for required in [false, true] {
@@ -671,25 +666,11 @@ async fn compiled_operation_preserves_reference_capture_budget_and_original_disp
         serde_json::json!({"description": "x".repeat(100_000)});
     let templates = OperationTemplate::for_contract(&original.contract).unwrap();
     let template = &templates["change"];
-    // Compact journal alone fits, but original full contract plus input exceeds its budget.
-    original.input = serde_json::json!("x".repeat(MAX_REQUEST - 50_000));
-    assert!(original.reference().is_err());
-    assert!(template.prepare(dynamic_request(&original)).is_err());
-    original.input = serde_json::json!("");
-    let overhead = encode(&original, MAX_REQUEST).unwrap().len();
-    original.input = serde_json::json!("x".repeat(MAX_REQUEST - overhead));
-    assert_eq!(encode(&original, MAX_REQUEST).unwrap().len(), MAX_REQUEST);
-    assert_eq!(
-        template
-            .prepare(dynamic_request(&original))
-            .unwrap()
-            .reference(),
-        &original.reference().unwrap()
-    );
-    original.input = serde_json::json!("x".repeat(MAX_REQUEST - overhead + 1));
-    assert!(original.reference().is_err());
-    assert!(template.prepare(dynamic_request(&original)).is_err());
-    original.input = serde_json::json!({"original": true});
+    original.input = serde_json::json!({
+        "text": "界😀\n\"\\\t".repeat(180_000),
+        "tail": {"complete": true, "original": "末尾"},
+    });
+    assert!(serde_json::to_vec(&original.input).unwrap().len() > 2 * 1024 * 1024);
     let mut invalid_consumer = dynamic_request(&original);
     invalid_consumer.consumer = InstanceId(vec![Uuid::nil()]);
     assert!(template.prepare(invalid_consumer).is_err());
@@ -704,6 +685,48 @@ async fn compiled_operation_preserves_reference_capture_budget_and_original_disp
     };
     assert_eq!(observation.reference, *claim.reference());
     assert_eq!(observation.outcome, OperationOutcome::Unresolved);
+    assert_eq!(observation.cleanup, OperationCleanup::Unconfirmed);
+    let outcome = OperationOutcome::Returned {
+        value: serde_json::json!({
+            "text": "结果😀\n\"\\\t".repeat(100_000),
+            "tail": {"complete": true, "original": "完整结果"},
+        }),
+    };
+    assert!(serde_json::to_vec(&outcome).unwrap().len() > 1024 * 1024 + 128);
+    let settled = store
+        .finish_operation(&claim, outcome.clone(), OperationCleanup::Confirmed)
+        .await
+        .unwrap();
+    assert_eq!(settled.reference, *claim.reference());
+    assert_eq!(settled.outcome, outcome);
+    assert_eq!(settled.cleanup, OperationCleanup::Confirmed);
+    assert_eq!(
+        store
+            .finish_operation(&claim, outcome, OperationCleanup::Confirmed)
+            .await
+            .unwrap(),
+        settled
+    );
+    let Dispatch::Existing(retried) = store.dispatch_operation(original.clone()).await.unwrap()
+    else {
+        panic!("settled original must not execute again")
+    };
+    assert_eq!(retried, settled);
+    let Dispatch::Existing(retried) = store
+        .dispatch_prepared_operation(template.prepare(dynamic_request(&original)).unwrap())
+        .await
+        .unwrap()
+    else {
+        panic!("settled prepared original must not execute again")
+    };
+    assert_eq!(retried, settled);
+    assert_eq!(
+        store
+            .operation_observation(claim.reference())
+            .await
+            .unwrap(),
+        Some(settled.clone())
+    );
     original.input = serde_json::json!({"replacement": true});
     assert!(matches!(
         store
@@ -711,6 +734,13 @@ async fn compiled_operation_preserves_reference_capture_budget_and_original_disp
             .await,
         Err(StoreError::EventConflict)
     ));
+    assert_eq!(
+        store
+            .operation_observation(claim.reference())
+            .await
+            .unwrap(),
+        Some(settled)
+    );
     drop(claim);
     store.close().await.unwrap();
 }
@@ -759,7 +789,7 @@ async fn contract_templates_keep_each_mutations_resources_and_request_identity()
                 assert_eq!(prepared.journal, original.journal().unwrap());
                 assert_eq!(
                     &*prepared.contract_json,
-                    encode(&original.contract, MAX_REQUEST).unwrap()
+                    serde_json::to_string(&original.contract).unwrap()
                 );
             }
         }
diff --git a/platform/host-js/tests/application_services.rs b/platform/host-js/tests/application_services.rs
index 2e147e51e2..e6c65fd2fa 100644
--- a/platform/host-js/tests/application_services.rs
+++ b/platform/host-js/tests/application_services.rs
@@ -211,6 +211,9 @@ fn consumer() -> Package {
         Some("export function activate() { return {}; }".into()),
     )
 }
+fn large_json_text() -> String {
+    "original界🙂\"\\\n\t".repeat(64 * 1024)
+}
 fn scope(issuer: &Issuer, allowed: bool) -> Scope {
     issuer
         .issue_with(
@@ -407,11 +410,7 @@ async fn authority_and_validation_reject_before_work_and_business_errors_settle_
                 .await
                 .is_err()
         );
-        for (method, input) in [
-            ("unknown", json!("input")),
-            ("echo", json!(false)),
-            ("echo", json!("x".repeat(1024 * 1024))),
-        ] {
+        for (method, input) in [("unknown", json!("input")), ("echo", json!(false))] {
             assert!(
                 client
                     .start(
@@ -426,6 +425,26 @@ async fn authority_and_validation_reject_before_work_and_business_errors_settle_
             );
         }
         assert_eq!(calls.load(Ordering::SeqCst), 0);
+        let original = json!(large_json_text());
+        let large_scope = scope(&issuer, true);
+        assert_eq!(
+            client
+                .start(
+                    binding.clone(),
+                    "echo".into(),
+                    original.clone(),
+                    large_scope.clone(),
+                    Attachments::new().into()
+                )
+                .await
+                .unwrap()
+                .result()
+                .await
+                .unwrap(),
+            original
+        );
+        large_scope.finish().await.unwrap();
+        assert_eq!(calls.load(Ordering::SeqCst), 1);
         for value in ["fail", "bad-result"] {
             assert!(
                 client
@@ -474,6 +493,118 @@ async fn authority_and_validation_reject_before_work_and_business_errors_settle_
     .unwrap();
 }
 
+async fn javascript_nested_echo_preserves_large_json(configuration: bool) {
+    tokio::time::timeout(Duration::from_secs(20), async {
+        for realm in [Realm::Shared, Realm::Dedicated] {
+            let implementation = Implementation::JavaScript {
+                module: "host.mjs".into(),
+                realm,
+            };
+            let mut declaration = entry(true, implementation.clone(), MethodMode::Query);
+            declaration.imports = entry(false, implementation, MethodMode::Query).imports;
+            let source = format!(
+                r#"
+                    let configuration;
+                    export const service = {{
+                        async echo(input, _observation, context) {{
+                            return await context.invoke({{
+                                operation: 'call', import: 'echo', provider: 0,
+                                method: 'echo', input: configuration.original ?? input,
+                                attachments: {{}}
+                            }});
+                        }}
+                    }};
+                    export function activate(config) {{
+                        configuration = config;
+                        return {{echo: {{contract: {}, service: ['service']}}}};
+                    }}
+                "#,
+                serde_json::to_string(&contract(MethodMode::Query)).unwrap()
+            );
+            let wrapper = package("forwarder", declaration, Some(source));
+            let provider = native_package();
+            let consumer = consumer();
+            let mut composition = input(&provider, &consumer);
+            let mut wrapper_node = node(&wrapper, 4, false);
+            let original = json!(large_json_text());
+            if configuration {
+                wrapper_node
+                    .configuration
+                    .values
+                    .insert("original".into(), original.clone());
+            }
+            composition.instances.insert("wrapper".into(), wrapper_node);
+            composition
+                .instances
+                .get_mut("a")
+                .unwrap()
+                .bindings
+                .get_mut("echo")
+                .unwrap()[0] = Target::Instance {
+                path: vec!["wrapper".into()],
+                export: "echo".into(),
+            };
+            let calls = Arc::new(AtomicUsize::new(0));
+            let issuer = Issuer::default();
+            let app = Application::start(
+                composition,
+                vec![provider, consumer, wrapper],
+                registry(Arc::new(Echo {
+                    calls: calls.clone(),
+                })),
+                issuer.clone(),
+                Arc::new(Grant(issuer.clone())),
+                Some(maka_host_js::factory(Limits::default())),
+            )
+            .unwrap();
+            app.ready().await.unwrap();
+            let client = app.client();
+            let binding = client
+                .bind(client.activation(&id(2)).unwrap(), "echo".into())
+                .await
+                .unwrap()
+                .remove(0);
+            let request_scope = scope(&issuer, true);
+            assert_eq!(
+                client
+                    .start(
+                        binding,
+                        "echo".into(),
+                        if configuration {
+                            json!("read configuration")
+                        } else {
+                            original.clone()
+                        },
+                        request_scope.clone(),
+                        Attachments::new().into(),
+                    )
+                    .await
+                    .unwrap()
+                    .result()
+                    .await
+                    .unwrap(),
+                original
+            );
+            request_scope.finish().await.unwrap();
+            assert_eq!(calls.load(Ordering::SeqCst), 1);
+            app.shutdown().await.unwrap();
+            assert!(client.snapshot().closed);
+        }
+    })
+    .await
+    .unwrap();
+}
+
+#[tokio::test]
+async fn javascript_nested_query_preserves_large_unicode_json() {
+    javascript_nested_echo_preserves_large_json(false).await;
+}
+
+#[tokio::test]
+async fn javascript_configuration_preserves_large_unicode_json() {
+    javascript_nested_echo_preserves_large_json(true).await;
+}
+
 struct Held {
     started: Arc<Semaphore>,
     release: Arc<Semaphore>,
diff --git a/platform/host-js/tests/application_services/operations.rs b/platform/host-js/tests/application_services/operations.rs
index a983c65b61..339f08c107 100644
--- a/platform/host-js/tests/application_services/operations.rs
+++ b/platform/host-js/tests/application_services/operations.rs
@@ -545,19 +545,28 @@ async fn original_receipt_survives_restart_and_new_composition_without_provider(
             .await
             .unwrap()
             .remove(0);
+        let original = large_receipt_value();
         let accepted = mutate(
             &client,
             &store,
             binding,
             "echo".into(),
-            json!("original"),
+            original.clone(),
             scope(&issuer, true),
             Uuid::new_v4(),
         )
         .await
         .unwrap();
         let reference = accepted.reference.clone();
-        returned(accepted.result().await);
+        assert_eq!(
+            accepted.result().await.receipt,
+            Receipt::Recorded {
+                outcome: OperationOutcome::Returned {
+                    value: original.clone()
+                },
+                cleanup: OperationCleanup::Confirmed,
+            }
+        );
         let mut declaration = entry(
             false,
             Implementation::JavaScript {
@@ -654,9 +663,7 @@ async fn original_receipt_survives_restart_and_new_composition_without_provider(
             .unwrap();
         assert_eq!(
             observation.outcome,
-            OperationOutcome::Returned {
-                value: json!("original")
-            }
+            OperationOutcome::Returned { value: original }
         );
         assert_eq!(observation.cleanup, OperationCleanup::Confirmed);
         assert_eq!(calls.load(Ordering::SeqCst), 2);
@@ -1194,6 +1201,10 @@ fn unknown(reply: OperationReply) -> bool {
     )
 }
 
+fn large_receipt_value() -> Value {
+    json!("回🙂\"\\\n".repeat(128 * 1024))
+}
+
 struct ReceiptBoundaryEcho(Arc<AtomicUsize>);
 impl Handler for ReceiptBoundaryEcho {
     fn call(&self, _: String, input: Value, _: Context) -> BoxFuture<'static, Result<Value>> {
@@ -1201,7 +1212,7 @@ impl Handler for ReceiptBoundaryEcho {
         Box::pin(async move {
             calls.fetch_add(1, Ordering::SeqCst);
             if input == json!("large") {
-                Ok(json!("x".repeat(1024 * 1024 - 2)))
+                Ok(large_receipt_value())
             } else if input == json!("integer") {
                 Ok(json!(9007199254740993_u64))
             } else {
@@ -1285,11 +1296,15 @@ async fn javascript_receipts_preserve_child_reference_unknown_and_oversized_reco
         assert_eq!(stored_integer.cleanup,OperationCleanup::Confirmed);
         assert_eq!(calls.load(Ordering::SeqCst),2);
         let large = read("large").await;
-        assert!(matches!(large.receipt,Receipt::Unavailable {..}));
+        assert!(matches!(&large.receipt,Receipt::Recorded {
+            outcome:OperationOutcome::Returned {value},
+            cleanup:OperationCleanup::Confirmed,
+        } if value == &large_receipt_value()), "expected the complete large returned value with confirmed cleanup; calls={}, unknown={}", calls.load(Ordering::SeqCst), matches!(&large.receipt, Receipt::Recorded { outcome: OperationOutcome::Unknown {..}, .. }));
         let stored = store.operation_observation(&large.reference).await.unwrap().unwrap();
-        assert_eq!(stored.outcome,OperationOutcome::Returned {value:json!("x".repeat(1024*1024-2))});
+        assert_eq!(stored.outcome,OperationOutcome::Returned {value:large_receipt_value()});
         assert_eq!(stored.cleanup,OperationCleanup::Confirmed);
-        assert_eq!(read("large").await.reference,large.reference);
+        assert_eq!(read("large").await,large);
+        assert_eq!(read("recover").await,large);
         assert_eq!(calls.load(Ordering::SeqCst),3);
         client.retire(client.activation(&id(1)).unwrap()).await.unwrap();
         let reader_binding = client.bind(client.activation(&id(6)).unwrap(),"echo".into()).await.unwrap().remove(0);
@@ -1397,16 +1412,17 @@ async fn original_contract_metadata_stays_native_while_compact_receipts_are_deli
     .await
     .unwrap();
     let reference = mutation.reference.clone();
-    maka_plugin_core::json::check_delivery(&serde_json::to_value(&reference).unwrap(), 1024)
-        .unwrap();
     let reply = mutation.result().await;
-    assert!(matches!(
+    assert_eq!(reply.reference, reference);
+    assert_eq!(
         reply.receipt,
         Receipt::Recorded {
-            outcome: OperationOutcome::Returned { .. },
+            outcome: OperationOutcome::Returned {
+                value: json!("effect")
+            },
             cleanup: OperationCleanup::Confirmed,
         }
-    ));
+    );
     assert_eq!(calls.load(Ordering::SeqCst), 1);
     app.shutdown().await.unwrap();
     drop(binding);
diff --git a/platform/host-js/tests/application_services/receipts.rs b/platform/host-js/tests/application_services/receipts.rs
index d7cc8e4c9f..7c5722599e 100644
--- a/platform/host-js/tests/application_services/receipts.rs
+++ b/platform/host-js/tests/application_services/receipts.rs
@@ -414,7 +414,7 @@ async fn composed_portable_receipts_preserve_exact_journal_values_and_original_r
                     cleanup: OperationCleanup::Confirmed
                 }
             ));
-            originals.push(original);
+            originals.push((input, original));
         }
         let (input, packages) = reader_source(json!({}));
         store
@@ -427,17 +427,16 @@ async fn composed_portable_receipts_preserve_exact_journal_values_and_original_r
         let reader = reader_application(store.clone(), deployment, &issuer, recovery).await;
         let client = reader.client();
         let binding = reader_binding(&client).await;
-        for original in originals {
-            assert!(
-                unavailable(read(&client, binding.clone(), &original.reference, &issuer).await)
-                    .contains("cannot be represented")
-            );
-            assert!(matches!(
-                script_read(&client, &original.reference, &issuer)
-                    .await
-                    .receipt,
-                Receipt::Unavailable { .. }
-            ));
+        for (input, original) in originals {
+            let observed = read(&client, binding.clone(), &original.reference, &issuer).await;
+            let scripted = script_read(&client, &original.reference, &issuer).await;
+            if input == "integer" {
+                assert!(unavailable(observed).contains("cannot be represented"));
+                assert!(matches!(scripted.receipt, Receipt::Unavailable { .. }));
+            } else {
+                assert_eq!(observed, original);
+                assert_eq!(scripted, original);
+            }
             let raw = client
                 .recover(
                     client.activation(&id(2)).unwrap(),
diff --git a/platform/host-runtime/README.md b/platform/host-runtime/README.md
index aae978fb69..f155e87247 100644
--- a/platform/host-runtime/README.md
+++ b/platform/host-runtime/README.md
@@ -25,7 +25,9 @@ Runs checked service compositions and owns call admission, activation and retire
 
 A committed source is desired configuration. It becomes effective only after its instances converge. Updates preserve unchanged activations and their captured bindings; replacements wait for accepted calls and native resources to settle. Mutation receipts distinguish business results from cleanup, so a lost reply must be resolved through its original receipt.
 
-Retiring either party of a subscription requests cancellation of its original invocation. The Host still waits for the handler and its native resources to settle before closing the provider. Accepted queries and mutations retain their original completion and cleanup semantics. Subscription and mutation-progress delivery use queue backpressure and consumer demand without a separate item-size quota. JavaScript bridge and IPC envelope requirements still apply at their respective boundaries.
+Retiring either party of a subscription requests cancellation of its original invocation. The Host still waits for the handler and its native resources to settle before closing the provider. Accepted queries and mutations retain their original completion and cleanup semantics. Subscription and mutation-progress delivery use queue backpressure and consumer demand without a separate item-size quota.
+
+Service inputs, outputs, configuration and original receipts have no separate JSON envelope quota in the Host or JavaScript request bridge. Accepted inputs still reserve shared capacity until their work settles; this does not bound output memory. Schema validation, JavaScript numeric precision and IPC framing requirements apply at their respective boundaries. A receipt that JavaScript cannot represent exactly remains available in its original journal.
 
 Complete source documents, including frozen remote contracts and package references, have a shared 2 MiB budget for admission, persistence and management. Read them in pages under one source revision; replace large documents through immutable resources.
 
diff --git a/platform/host-runtime/README.zh-CN.md b/platform/host-runtime/README.zh-CN.md
index 9f1946ec15..8073340933 100644
--- a/platform/host-runtime/README.zh-CN.md
+++ b/platform/host-runtime/README.zh-CN.md
@@ -25,7 +25,9 @@
 
 提交的配置表示期望状态,实例完成收敛后才成为有效状态。更新保留未改变的激活及其绑定;替换必须等待已接受调用和原生资源完成清理。操作回执区分业务结果与清理状态,丢失响应后应查询原回执。
 
-订阅的提供方或调用方退役时,Host 请求取消原订阅调用,并在原处理程序及其原生资源完成清理后关闭提供方。已受理的查询和变更仍保留原有完成与清理语义。订阅和变更进度通过队列背压和消费者需求控制交付,不另设单项大小额度。JavaScript 桥和 IPC 信封要求仍在各自边界生效。
+订阅的提供方或调用方退役时,Host 请求取消原订阅调用,并在原处理程序及其原生资源完成清理后关闭提供方。已受理的查询和变更仍保留原有完成与清理语义。订阅和变更进度通过队列背压和消费者需求控制交付,不另设单项大小额度。
+
+Host 和 JavaScript 请求桥不对服务输入、输出、配置和原始回执另设 JSON 大小额度。已受理的输入仍占用共享容量,直至实际工作完成清理;这不限制输出的内存占用。schema 校验、JavaScript 数值精度和 IPC 帧要求在各自边界生效。JavaScript 无法精确表示的回执仍保存在原始日志中。
 
 完整配置文档包含冻结的远端契约和包引用,准入、持久化与管理共用 2 MiB 预算。读取时固定配置版本并逐页获取;较大文档通过不可变资源替换。
 
diff --git a/platform/host-runtime/src/application.rs b/platform/host-runtime/src/application.rs
index 0eab42def9..9f3a062282 100644
--- a/platform/host-runtime/src/application.rs
+++ b/platform/host-runtime/src/application.rs
@@ -1164,15 +1164,10 @@ impl Client {
     }
 }
 
-fn check_json(value: &Value) -> Result<usize> {
-    check_json_limit(value, 1024 * 1024)
-}
-
-// Leave room for receipt status and bounded diagnostics in the 1 MiB JS envelope.
 fn check_reference(reference: &RecoveryRef) -> Result<usize> {
     maka_plugin_core::json::check_delivery(
         &serde_json::to_value(reference).map_err(|e| e.to_string())?,
-        512 * 1024,
+        usize::MAX,
     )
     .map_err(|e| e.to_string())
 }
@@ -1211,7 +1206,7 @@ impl Dispatch {
     ) -> Result<()> {
         // Early validation also drops physical input before its inert ticket.
         let custody = (attachments, parent);
-        let size = check_json(&input)?;
+        let size = maka_plugin_core::json::value_size(&input, usize::MAX)?;
         if method.is_empty() || method.len() > 128 {
             return Err("invalid service method".into());
         }
@@ -1250,7 +1245,9 @@ impl Dispatch {
         let bytes = self
             .bytes
             .clone()
-            .try_acquire_many_owned(size.max(1) as u32)
+            .try_acquire_many_owned(
+                u32::try_from(size.max(1)).map_err(|_| "Host recovery budget exhausted")?,
+            )
             .map_err(|_| "Host recovery budget exhausted")?;
         let (reply, result) = oneshot::channel();
         self.commands
@@ -1311,7 +1308,6 @@ fn prepare_plan(
         .map(|p| (p.application_ref(), p))
         .collect();
     for instance in plan.instances().values().filter(|i| !i.disabled) {
-        check_json(&instance.configuration)?;
         if let Some(entry) = &instance.entry {
             for export in entry.exports.values() {
                 let Interface::Service { methods } = &export.contract.interface else {
diff --git a/platform/host-runtime/src/application/operations.rs b/platform/host-runtime/src/application/operations.rs
index c2d89c1a61..150d961573 100644
--- a/platform/host-runtime/src/application/operations.rs
+++ b/platform/host-runtime/src/application/operations.rs
@@ -109,12 +109,12 @@ pub(super) fn receipt_reply(
 // Delivery failure must never replace the original journal's durable outcome.
 pub(super) fn receipt_value(mut reply: OperationReply) -> Result<Value> {
     let value = serde_json::to_value(&reply).map_err(|e| e.to_string())?;
-    if maka_plugin_core::json::check_delivery(&value, 1024 * 1024).is_ok() {
+    if maka_plugin_core::json::exact_numbers(&value).is_ok() {
         return Ok(value);
     }
     reply.receipt = Receipt::Unavailable { diagnostic: "original receipt cannot be represented by this observer; read original journal through a compatible observer".into() };
     let value = serde_json::to_value(reply).map_err(|e| e.to_string())?;
-    maka_plugin_core::json::check_delivery(&value, 1024 * 1024).map_err(|e| e.to_string())?;
+    maka_plugin_core::json::exact_numbers(&value)?;
     Ok(value)
 }
 
diff --git a/platform/host-runtime/src/application/owner.rs b/platform/host-runtime/src/application/owner.rs
index 199d901a5e..0396aae9ad 100644
--- a/platform/host-runtime/src/application/owner.rs
+++ b/platform/host-runtime/src/application/owner.rs
@@ -1205,9 +1205,14 @@ impl Owner {
                                 return Err("Host attachment slots or types mismatch".into());
                             }
                             let size = resource_ingress::attachment_size(&attachments)?;
+                            let input_size =
+                                maka_plugin_core::json::value_size(&input, usize::MAX)?.max(1);
+                            let bytes_needed = size
+                                .descriptors
+                                .checked_add(input_size)
+                                .ok_or("Host input budget exhausted")?;
                             if size.payload != resources.num_permits()
-                                || size.descriptors + check_json(&input)?.max(1)
-                                    > bytes.num_permits()
+                                || bytes_needed > bytes.num_permits()
                             {
                                 return Err(
                                     "Host attachment descriptor changed before admission".into()
@@ -1412,7 +1417,6 @@ impl Owner {
                                 if scope.cancellation.is_cancelled() { return Err("Host invocation was revoked before callback".into()); }
                                 let service = execution.value();
                                 let value = service.implementation.call(method.clone(), input, context).await?;
-                                check_json(&value)?;
                                 service.methods[&method].output.validate(&value).map_err(|e| e.to_string())?;
                                 Ok(value)
                             };
diff --git a/platform/host-runtime/src/application/requests.rs b/platform/host-runtime/src/application/requests.rs
index 92698860fd..db3e490349 100644
--- a/platform/host-runtime/src/application/requests.rs
+++ b/platform/host-runtime/src/application/requests.rs
@@ -121,7 +121,6 @@ impl Context {
                     metadata: resource.metadata(),
                 })
                 .map_err(|error| error.to_string())?;
-                check_json(&value)?;
                 Ok(value)
             }
             HostRequest::Read { start, end, .. } => {
diff --git a/platform/host-runtime/src/application/resource_ingress.rs b/platform/host-runtime/src/application/resource_ingress.rs
index 99acae1583..1f987962ec 100644
--- a/platform/host-runtime/src/application/resource_ingress.rs
+++ b/platform/host-runtime/src/application/resource_ingress.rs
@@ -361,7 +361,10 @@ impl Dispatch {
                 let input = self
                     .bytes
                     .clone()
-                    .try_acquire_many_owned(input_size.max(1) as u32)
+                    .try_acquire_many_owned(
+                        u32::try_from(input_size.max(1))
+                            .map_err(|_| "Host input budget exhausted")?,
+                    )
                     .map_err(|_| "Host input budget exhausted")?;
                 reserved.bytes.merge(input);
                 Ok(*reserved)
@@ -381,10 +384,15 @@ impl Dispatch {
                         return Err(error);
                     }
                 };
+                let bytes_needed = input_size
+                    .max(1)
+                    .checked_add(size.descriptors)
+                    .and_then(|size| u32::try_from(size).ok())
+                    .ok_or("Host input budget exhausted")?;
                 let bytes = self
                     .bytes
                     .clone()
-                    .try_acquire_many_owned((input_size.max(1) + size.descriptors) as u32)
+                    .try_acquire_many_owned(bytes_needed)
                     .map_err(|_| "Host input budget exhausted")?;
                 let resources = self
                     .resources
diff --git a/platform/js-runtime/src/plugin/captured.rs b/platform/js-runtime/src/plugin/captured.rs
index 4b853c8fb9..8a1b8bdf70 100644
--- a/platform/js-runtime/src/plugin/captured.rs
+++ b/platform/js-runtime/src/plugin/captured.rs
@@ -87,14 +87,16 @@ impl Captured {
         }
         let module = &self.0.module;
         module.ready().await?;
-        let size = json::encoded_size(&args, 1024 * 1024).map_err(failed)?;
+        let size = json::encoded_size(&args, usize::MAX).map_err(failed)?;
         let bytes = module
             .0
             .vm
             .0
             .bytes
             .clone()
-            .try_acquire_many_owned(size.max(1) as u32)
+            .try_acquire_many_owned(
+                u32::try_from(size.max(1)).map_err(|_| failed("VM input budget exhausted"))?,
+            )
             .map_err(|_| failed("VM input budget exhausted"))?;
         let (reply, result) = oneshot::channel();
         module
@@ -132,14 +134,16 @@ impl Module {
         {
             return Err(failed("invalid worker callback registration"));
         }
-        let size = json::encoded_size(&(&namespace, &methods), 1024 * 1024).map_err(failed)?;
+        let size = json::encoded_size(&(&namespace, &methods), usize::MAX).map_err(failed)?;
         let bytes = self
             .0
             .vm
             .0
             .bytes
             .clone()
-            .try_acquire_many_owned(size.max(1) as u32)
+            .try_acquire_many_owned(
+                u32::try_from(size.max(1)).map_err(|_| failed("VM input budget exhausted"))?,
+            )
             .map_err(|_| failed("VM input budget exhausted"))?;
         let (reply, result) = oneshot::channel();
         self.0
diff --git a/platform/js-runtime/src/plugin/request.rs b/platform/js-runtime/src/plugin/request.rs
index dc1cc096dd..c2886d9391 100644
--- a/platform/js-runtime/src/plugin/request.rs
+++ b/platform/js-runtime/src/plugin/request.rs
@@ -78,7 +78,7 @@ impl<'a> FromV8<'a> for Input {
         scope: &mut v8::PinScope<'a, 'i>,
         value: v8::Local<'a, v8::Value>,
     ) -> std::result::Result<Self, Self::Error> {
-        decode(scope, value, Some(1024 * 1024)).map(Self)
+        decode(scope, value, None).map(Self)
     }
 }
 
@@ -92,7 +92,7 @@ async fn op_maka_request(
         .0
         .upgrade()
         .ok_or_else(|| JsErrorBox::generic("request context expired"))?;
-    let size = super::json::encoded_size(&input.0, 1024 * 1024)
+    let size = super::json::encoded_size(&input.0, usize::MAX)
         .map_err(|e| JsErrorBox::generic(e.to_string()))?;
     let _bytes = {
         let state = state.borrow();
@@ -100,7 +100,10 @@ async fn op_maka_request(
             .borrow::<Budget>()
             .bytes
             .clone()
-            .try_acquire_many_owned(size.max(1) as u32)
+            .try_acquire_many_owned(
+                u32::try_from(size.max(1))
+                    .map_err(|_| JsErrorBox::generic("request operation input budget exhausted"))?,
+            )
             .map_err(|_| JsErrorBox::generic("request operation input budget exhausted"))?
     };
     // The observer owns no ContextState. A saved Promise or native cppgc root
@@ -114,8 +117,6 @@ async fn op_maka_request(
         .await
         .map_err(|_| JsErrorBox::generic("request observer panicked"))?
         .map_err(|e| JsErrorBox::generic(e.to_string()))?;
-    maka_plugin_core::json::check_delivery(&output, 1024 * 1024)
-        .map_err(|e| JsErrorBox::generic(e.to_string()))?;
     tokio::task::yield_now().await;
     Json::encode(&output)
 }
diff --git a/platform/js-runtime/tests/integration/plugin_vm/captured.rs b/platform/js-runtime/tests/integration/plugin_vm/captured.rs
index f4d054fbf9..8b5130185d 100644
--- a/platform/js-runtime/tests/integration/plugin_vm/captured.rs
+++ b/platform/js-runtime/tests/integration/plugin_vm/captured.rs
@@ -214,7 +214,6 @@ async fn worker_registration_checks_input_result_json_and_registration_shapes()
         }
         assert!(module.capture(vec!["service".into();33], vec!["read".into()]).await.is_err());
         let callbacks = module.capture(vec!["service".into()], vec!["read".into(),"json".into(),"circular".into()]).await.unwrap();
-        assert!(callbacks.call("read", vec![json!("x".repeat(1024*1024))]).await.is_err());
         for value in [json!(u64::MAX), json!(i64::MAX), json!(9_007_199_254_740_993_u64)] {
             assert!(callbacks.call("read", vec![json!({"nested":[value]})]).await
                 .unwrap_err().to_string().contains("represented exactly"));
@@ -307,7 +306,7 @@ impl RequestBridge for CountInput {
     }
 }
 #[tokio::test]
-async fn native_bridge_checks_vm_json_input_before_copy_and_before_dispatch() {
+async fn native_bridge_checks_json_and_input_capacity_before_dispatch() {
     tokio::time::timeout(Duration::from_secs(10), async {
         let vm = Vm::scoped(Limits::default()).unwrap();
         let calls = Arc::new(std::sync::atomic::AtomicUsize::new(0));
@@ -315,7 +314,7 @@ async fn native_bridge_checks_vm_json_input_before_copy_and_before_dispatch() {
             export const service = { async read(mode, context) {
                 const input = mode==='bigint' ? {nested:[9007199254740993n]} : {text:'x'.repeat(32*1024*1024)};
                 try { await context.invoke(input); return false; }
-                catch(error) { return error.message.includes(mode==='bigint'?'BigInt':'1 MiB'); }
+                catch(error) { return error.message.includes(mode==='bigint'?'BigInt':'input budget'); }
             }};
         "#.into()).unwrap();
         let callbacks = capture_result(&module).await.unwrap();
diff --git a/platform/js-runtime/tests/integration/plugin_vm/request.rs b/platform/js-runtime/tests/integration/plugin_vm/request.rs
index 89b1cdf2e8..6e6b781197 100644
--- a/platform/js-runtime/tests/integration/plugin_vm/request.rs
+++ b/platform/js-runtime/tests/integration/plugin_vm/request.rs
@@ -58,9 +58,9 @@ async fn private_contexts_expire_before_reply_without_an_ambient_or_json_address
                 async stale() { try { await saved.invoke('old'); return false; } catch(e) { return e.message.includes('expired'); } },
                 async invalid(mode, context) {
                     try {
-                        await context.invoke(mode==='large'? 'x'.repeat(1024*1024):mode==='bigint'?1n:'inexact');
+                        await context.invoke(mode==='bigint'?1n:'inexact');
                         return false;
-                    } catch(e) { return e.message.includes(mode==='large'?'1 MiB':mode==='bigint'?'BigInt':'represented exactly'); }
+                    } catch(e) { return e.message.includes(mode==='bigint'?'BigInt':'represented exactly'); }
                 },
                 mutateIntrinsics() { Object.freeze=()=>{throw Error('poisoned freeze')}; }
             };
@@ -73,7 +73,7 @@ async fn private_contexts_expire_before_reply_without_an_ambient_or_json_address
         assert!(weak.upgrade().is_none(), "reply cannot precede ContextState release");
         assert_eq!(callbacks.call("stale", vec![]).await.unwrap(), json!(true));
         assert!(callbacks.call("read", vec![json!("forged"),json!({"invoke":"1","moduleId":1})]).await.is_err());
-        for mode in ["large","bigint","inexact"] {
+        for mode in ["bigint","inexact"] {
             assert_eq!(callbacks.call_with_context("invalid", vec![json!(mode)], Arc::new(Echo { label:mode.into(),calls:calls.clone() })).await.unwrap(), json!(true));
         }
         assert_eq!(calls.load(Ordering::SeqCst), 2, "invalid inputs never dispatch");
diff --git a/platform/ui-runtime/src/actions/mutations.rs b/platform/ui-runtime/src/actions/mutations.rs
index 2104292b69..0584192b8f 100644
--- a/platform/ui-runtime/src/actions/mutations.rs
+++ b/platform/ui-runtime/src/actions/mutations.rs
@@ -184,9 +184,8 @@ impl<V: ?Sized + 'static> Application<V> {
                 let prepared = async {
                     let original = owner.prepare().await?;
                     original.validate().map_err(|e| e.to_string())?;
-                    maka_plugin_core::json::check_delivery(
+                    maka_plugin_core::json::exact_numbers(
                         &serde_json::to_value(&original).map_err(|e| e.to_string())?,
-                        512 * 1024,
                     )
                     .map_err(|e| e.to_string())?;
                     if original.operation != id {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org