Public Owned Data API v1
September 19, 2026 · View on GitHub
Status: implemented bounded Project-v8 API; generated packages remain unpublished and formal public promotion remains open. Release regression evidence is HOSTED GREEN under the v0.4.0 release baseline.
Audience: language users, generated-SDK consumers, tool authors, and compiler contributors.
GitHub issue #145 chose this
exact profile as the candidate for a maintained, reproducible generated-package
consumer route. scripts/generated-package-release.py prepares a preview
bundle (deterministic README/LICENSE/checksum manifest around the compiler's
own unchanged output) and dry-run-checks it; it never publishes anything. See
docs/GENERATED-PACKAGE-PUBLICATION-DECISION-DRAFT-V1.md
for the unapproved draft maintainer decision this prepares for.
Public Owned Data API v1 defines one additive Project profile for calling a
closed set of stable-ID functions from JavaScript/TypeScript and safe Rust. It
extends the existing fixed-memory byte-data mechanism with controlled owned
byte results. Project Manifest v8, both generated consumer routes, the
reference-interpreter lane, and their focused evidence are present in the
current source tree. The v0.2.0 tag commit
5f6fb9655fdec92c57ab71615cfd7bfa8cc76051 passed the complete blocking
release run,
including the three-host Rust inventories and selected consumer/sanitizer
jobs. This supersedes authoring-time “unrun” wording only for nonignored tests
actually selected by that workflow. It does not publish either generated
package, execute every separately provisioned case, or complete formal API
promotion.
The profile deliberately copies every successful owned result into host-owned storage before publication. It does not expose a SEMAPRAX pointer, allocator, arena token, or provider handle to application code.
Fixed protocol identifiers
The following identifiers are exact and are not aliases:
| Layer | Identifier |
|---|---|
| Project schema | semaprax.project.v8 |
| Project profile | owned-data-api.v1 |
| Canonical API descriptor | semaprax.public-owned-data-api.v1 |
| npm build carrier | semaprax.project-npm-build.v7 |
| npm API metadata | semaprax.owned-data-api.v1 |
| Rust SDK manifest | semaprax.native-rust-owned-data-sdk.v1 |
Each identifier selects only the contract in this document. An earlier
Project schema cannot select owned-data-api.v1, and Project v8 cannot select
an earlier profile. Consumers must reject unknown identifiers rather than
fall back to a scalar, useful-data, command, or legacy SDK route.
Canonical Project manifest
Project v8 has exactly eight assignments in this order and one terminal LF:
schema = "semaprax.project.v8"
name = "frame-payload"
version = "0.1.0"
profile = "owned-data-api.v1"
entry = "frame_payload.app"
sources = ["src/app.spx", "src/core.spx", "src/tests.spx"]
web_exports = ["frame.payload", "frame.payload-maybe", "frame.payload-result"]
tests = ["frame_payload.tests"]
The existing canonical name, Semantic Versioning, module, source-path,
stable-ID, and ordering rules apply unchanged. sources contains 2–16
strictly sorted unique paths. A public API selects 1–32 strictly sorted unique
web_exports stable IDs. The additive IO Cursors v1
library route also admits web_exports = [] for ordinary Project v8 libraries.
It checks and executes internal entry/test closures without producing a public
descriptor or public package artifact. Public artifact requests remain refused;
a nonempty export selection still uses every original public API rule.
The exact bundled std.collections and std.mem no-export alias packages
retain their additional source and inventory authentication and reject nonempty
exports for those exact manifest shapes. Other libraries gain no intrinsic-alias
authority from an empty export list. There are no command, input, or
capabilities fields. Unknown, missing, extra, duplicated, or reordered
assignments reject.
Project v8 enters the existing closed ProjectProfile dispatch as one distinct
variant. Schema or profile text is never converted into loose feature flags
from which downstream authority is inferred.
Semantic admission
Admission is derived from validated, linked HIR. Source-shaped declarations, generated metadata, target artifacts, or caller assertions are not semantic authority.
Every selected export must satisfy all of the following (the authenticated
no-export std.collections package selects none):
- it is a source-authored function with an explicit persistent
@idequal to the selectedweb_exportsidentity; - it is monomorphic and is not the Project entry function;
- it has 0–8 parameters, each with one exact admitted parameter type;
- it has exactly one result with one exact admitted result type;
- the function and every function in its transitive closure are effect-free, import-free, and contract-free;
- the complete selected closure is acyclic; direct and mutual recursion both reject;
- the linked executable function inventory is nonempty and contains at most the existing public-export bound of 256 functions; and
- the closure passes the ordinary verifier, ownership checks, cleanup-plan construction, and independent cleanup-plan replay before descriptor or target generation.
All selected roots, including roots disconnected from the Project entry, are linked under one authenticated held Project snapshot. The union of their closures is checked once; a function reachable from more than one root is not duplicated or charged twice.
Admitted types
The parameter vocabulary is exactly:
i64boolborrow strborrow Slice<u8>
The result vocabulary is exactly:
i64boolusizeBytesOption<Bytes>Result<Bytes, i64>
Option and Result here are the authenticated compiler-owned variants.
They are admitted only in the exact unnested forms above. Result::Err is a
successful API invocation carrying a language value; it is not an adapter or
host-call failure.
Borrowed arguments are invocation-bounded snapshots. Their cumulative encoded
or byte length across one external call is at most 65,536 bytes. An owned byte
result has an exact length in 0..=65_536; capacity-plus-one rejects before a
host value becomes observable.
Exact exclusions
The public boundary rejects all of the following, even when the shape exists inside an otherwise valid SEMAPRAX program:
- owned parameters;
- resource parameters or results;
- fixed arrays or any other arrays as public values;
- borrowed results;
- authored records;
- authored variants;
- nested
OptionorResultvalues; Resulterror types other than exactlyi64;- callbacks or callable imports;
- async functions or async values;
- shared values;
- public mutation or mutable borrowed arguments;
- multiple returned values or unit results;
- host allocator adoption or zero-copy allocator transfer; and
- direct raw pointer, arena-token, provider-handle, or context exposure.
The profile also grants no filesystem, process, environment, clock, random, network, thread, UI, registry, signing, or publication authority.
Canonical public API descriptor
The compiler derives one canonical descriptor from the authenticated Project
revisions, Project graph digest, validated HIR, selected stable IDs, and fixed
limits. Its schema is semaprax.public-owned-data-api.v1. It contains, in
strict stable-ID order:
- the Project schema, Project revision, Workspace revision, and Project graph digest;
- every export stable ID;
- every parameter's stable identity, source display name, ordinal, and one closed parameter-type tag;
- one closed result-type tag for each export; and
- the exact export, parameter, closure-function, borrowed-input, and owned-output limits.
The descriptor has deterministic canonical bytes and a domain-separated digest. Parsing is closed and bounded. Independent replay must reconstruct the same facts from the same retained Project subject and reject truncation, insertion, deletion, reordering, duplication, unknown fields or tags, changed revisions, changed graph digest, or any byte mutation.
The lower native package applies its existing nonempty, 1 MiB, terminal-LF
and NUL-free byte guard before JSON parsing, including the preliminary schema
lookup that selects the v8/v10 digest domain. Digest discovery and full replay
share that guard; reaching the exact byte limit does not establish canonical
or semantic validity. Provider-validation precedence and accepted descriptor
bytes remain unchanged. The focused regressions in
crates/semaprax-native-rust-owned-data-package/src/descriptor_input_tests.rs
cover exact/plus-one input framing, canonical replay, domain separation and
early rejection through the public builder. They are implemented.
The shared native provider-binding check also compares borrowed text rather than formatting a copy of the caller-supplied digest. It retains the exact single-binding-line predicate, including rejection of duplicate or malformed lines, without imposing a new digest grammar or changing error precedence. The same released regression module compares the old and new predicates on hostile line/digest combinations and an oversized digest mismatch.
The lower native package reader enforces parameter-identity uniqueness within
each export, matching the compiler's descriptor parser. Correctly recomputing
the digest does not authorize two parameter ordinals to share an identity.
This shared v8/v10 rejection leaves canonical compiler-produced bytes and
identifier grammars unchanged. It is a structural replay check, not independent
proof of provider semantics. Implemented regressions live in
tests/projections/public_api_descriptor/parameter_identity.rs and
crates/semaprax-native-rust-owned-data-package/src/descriptor/tests.rs:
the root cases retain real HIR and exact canonical framing while reminting
duplicate-ID mutations; lower cases cover both schemas and valid parameter
boundaries as well as duplicates. Structural uniqueness is per export, not a
new cross-export identity rule.
The additional tests/projections/public_api_descriptor/semantic_replay.rs cases
distinguish retained-HIR binding from framing and digest rejection. Each pair
derives two authentic descriptors from separately checked source, first
replays each against its own HIR, then cross-replays both directions using
their correct digests and requires the exact retained-subject diagnostic.
V8 and v10 cover parameter types, names, order and arity, scalar and owned
result types; v10 additionally distinguishes Bytes from owned UTF-8. Explicit
fact assertions keep these cases from degenerating into unrelated mutations.
The fixture deliberately holds synthetic revision facts constant to isolate signature replay. It does not claim an edited real Project retains its revision, that a descriptor authenticates source provenance, or that equal descriptors prove equal function behavior. Body-only and function-display-name controls preserve descriptor bytes; parameter presentation names are included facts. Parameter IDs derive from function identity and ordinal, so no independent source-authored parameter-ID mutation is claimed. These added cases are included in the v0.4.0 hosted-green regression corpus; production code, schemas and existing golden bytes remain unchanged.
This descriptor is the sole semantic API source for JavaScript bindings, TypeScript declarations, npm metadata, native provider descriptors, and the safe Rust SDK. A target may add authenticated target-layout facts, but it may not rediscover or reinterpret a source signature. If two targets require different semantic descriptors, the profile must remain inactive.
Display names are presentation only. Generated APIs are keyed by, or derive their collision-checked host identifier from, the persistent stable ID. A source display rename that preserves the stable ID must preserve descriptor meaning and the external API.
Host type mappings
| SEMAPRAX | TypeScript | Rust |
|---|---|---|
i64 | bigint | i64 |
bool | boolean | bool |
usize | bigint | u64 |
borrow str | string | &str |
borrow Slice<u8> | Uint8Array | &[u8] |
Bytes | Uint8Array | Vec<u8> |
Option<Bytes> | Uint8Array | null | Option<Vec<u8>> |
Result<Bytes, i64> | SemapraxResult<Uint8Array, bigint> | Result<Vec<u8>, i64> |
TypeScript uses this exact result definition:
export type SemapraxResult<T, E> =
| { readonly ok: true; readonly value: T }
| { readonly ok: false; readonly error: E };
JavaScript accepts only ordinary, attached, fixed-length Uint8Array byte
inputs. It rejects shared, resizable, detached, differently typed, DataView,
and implicitly coercible inputs. Strings are encoded as checked UTF-8. Every
borrowed argument is snapshotted before public scratch is mutated, and the
complete call is synchronous and non-reentrant.
For safe Rust, adapter, semantic, or host-call failure is an outer SDK error.
The table's Result<Vec<u8>, i64> is the successful SEMAPRAX language value
inside that outer result. Generated safe API code forbids unsafe code and
exposes no raw provider handle or context.
Result representation and lifetime
The target-neutral variant discriminants are fixed:
Option: None = 0, Some = 1
Result: Ok = 0, Err = 1
Any other tag is an invariant failure before payload access. None and Err
own no byte carrier. Some and Ok own exactly one active byte carrier.
Inactive payload storage is never read, copied, or dropped. A tag/liveness
disagreement fails before publication.
Before a generated API call returns to JavaScript or safe Rust, it must complete this sequence in order:
- authenticate the SEMAPRAX owned result and its active-case liveness;
- query and check its exact length against the authenticated carrier and the 65,536-byte output bound;
- allocate exact host-owned storage and copy exactly that many bytes;
- consume or drop the SEMAPRAX carrier exactly once;
- prove the invocation's provider or arena is settled, with no live result, provisional result, or cleanup obligation remaining; and
- only then publish the host-owned
Uint8Array,Vec<u8>,null, or error branch to application code.
The host allocation is never adopted by SEMAPRAX, and SEMAPRAX allocation is never adopted by the host. Empty owned bytes still carry real ownership until settled. Failure before result publication preserves the caller-visible result slot and exposes no partial bytes. Failure after staging but before publication settles the staged owner exactly once. If exact settlement cannot be proven, the invocation fails closed and publishes no language value.
The Wasm wrapper never exposes its raw carrier. It clears or poisons temporary
result storage after settlement and requires an empty arena before success.
The native provider uses an opaque, provider-owned handle only inside the
private FFI sibling; safe Rust queries length, copies, and settles through an
internal owner guard. A separate invocation guard then proves the entire
context settled through the existing context-close operation before returning
any value or recoverable error, including scalars, None, and language Err.
On Rust unwind the owner guard runs before the invocation guard. Uncertain
owner or context settlement retains the existing fail-stop policy; no retry or
later provider effect is permitted. Unknown tags or forged inactive handles
never authorize length, copy, or drop operations. A panic may not cross the
FFI boundary. No allocator pointer is converted directly into a Vec<u8>.
The authored v8/v9/v10 Rust correction reinitializes a proven-closed context only on the next invocation. This resets its private invocation counter, not the linked provider's nonreused handle issuer. No live result or provider obligation may cross that reset. A rejected initialization preserves its existing error and permits no further provider operation in that invocation or its cleanup; a later explicit invocation may attempt initialization again. Only a successfully initialized invocation owns a context-close obligation. Public Rust signatures, provider C and ABI, descriptors, and manifest schemas stay unchanged; generated safe/private Rust and its integrity bindings intentionally change. Hostile-provider protocol tests are implemented; this is not a safety claim against arbitrary malicious native machine code.
The subsequent native internal String correction settles String allocations that the standalone descriptor already admits inside function bodies. Provider context close cannot observe those inline allocations and is not their cleanup proof. V8/v9 provider emission now shares ordinary length-header helpers and a per-function String ledger. Full translation units with Strings, including unselected functions, intentionally change native C and dependent artifact bindings; String-free output remains exact. Public types, descriptors, schemas, v10 output, and activated Project admission are unchanged. Physical allocator and external-consumer evidence is implemented.
The authored native correction uses a 13-bit one-based slot (1..=4096)
and a nonreused 51-bit issuance serial within one statically linked provider
runtime. One private atomic strong compare-exchange reserves a serial without
retry. Contention or permanent exhaustion rejects before owner or output
publication; the caller settles its unpublished result. The issuer survives
context disposal and storage reinitialization. It does not establish uniqueness
across separate provider images or reloads, pointer secrecy, shared-context
thread safety, or guaranteed successful progress under contention. The same
private runtime correction applies to v9/v10; generated C/object/archive bytes
and integrity bindings intentionally change, not public signatures or schemas.
Scoped local execution of public_native_rust_owned_data_sdk_v1 on Linux
AArch64/Rust 1.88/Clang 14 passes nine selected tests: seven provider/SDK tests
and two target-management support checks. The native probes exercise hostile
handles, all 4,096 slots, context reincarnation, serial exhaustion and contention,
and separate thread-confined contexts at O0/O2; the provider/issuer probes also
run the Linux O2 sanitizer lane. The UTF-8 rejection probe runs at O0/O2.
The nested offline Cargo package-consumer test is explicitly excluded. The
Windows path-budget support check is a model, not Windows execution. These
results do not establish shared-context safety, full native support, hosted
promotion or physical allocator settlement for internal Strings.
The authored v8/v9/v10 JavaScript correction admits the entire argument tuple,
including exact bounded UTF-8 lengths, before payload snapshot allocation.
Captured intrinsic view checks reject detached/shared/resizable and wrong-brand
inputs without invoking caller constructor/species hooks. All snapshots still
precede Wasm scratch writes and arena entry. Module-byte inputs have their
separate 16 MiB admission bound before copy/hash. Explicit v9/v10 routing now
reuses the byte-identical v8 input helper; v8 JavaScript remains unchanged by
that extension. V9/v10 JavaScript and dependent artifact bindings intentionally
change, not descriptors, Wasm, or TypeScript declarations. Their record-field
authentication, scalar validation, and consume-before-UTF-8-decoding rules
remain in force. Real-package hostile-input regressions are release-tested, not promotion evidence; their owner is
tests/project/owned_input_admission.rs,
alongside the preserved v8 renderer known answers.
The Node evidence requires actual shared and resizable buffers plus transfer
support; missing prerequisites fail the selected gate rather than omit cases.
Buffer construction and capability checks happen outside rejection assertions.
The direct-Bytes fixture and shared v8/v9/v10 input-admission fixture require the
actual facade's TypeError and fixed-input diagnostic, followed by healthy
same-instance calls. An assertion that a forbidden input was accepted must not
be swallowed by a capability-detection catch. The direct/variant v8 and UTF-8
consumer tests also require Node execution instead of returning success when
Node cannot start. These evidence corrections are included in the v0.4.0 hosted-green regression corpus; generated
runtime bytes, schemas, and support status are unchanged.
The subsequent owned npm invocation correction reserves busy state before preflight and distinguishes reusable input rejection from post-entry uncertainty. Only a locally authenticated checked-status error may recover after settlement. Caught reentry, malformed output and unexpected host exceptions poison the instance even with an empty arena; the first thrown value is preserved without truthiness checks. This correction intentionally changes v8/v9/v10 JavaScript and its dependent integrity bindings, including the bounded-renderer known answers. Historical unselected renderers, Wasm, descriptors, declarations and v1-v7 artifacts remain unchanged. Its separate real-package failure matrix has scoped local execution evidence recorded in that contract; it does not promote the entire public profile.
Generated artifacts and carriers
The npm output inventory is exactly:
app.wasmsemaprax.jssemaprax.bindings.jssemaprax.bindings.d.tssemaprax.api.jsonpackage.json
semaprax.api.json uses semaprax.owned-data-api.v1 and binds the canonical
API descriptor, Wasm digest, fixed limits, exact target call shapes, ordered
artifact inventory, and owned-result settlement policy. The surrounding
context-bound npm build carrier uses semaprax.project-npm-build.v7 and binds
the retained Project subject plus the exact ordered artifacts, bytes, digests,
and payload digest. Inspection or replay proves consistency only; neither the
metadata nor carrier grants build or publication authority.
Filesystem materialization uses the shared Unix npm publication boundary: final parent binding compares held/reopened filesystem identities as well as canonical path text. Same-path parent replacement must not turn a package retained in a displaced directory into reported success. The admitted release regressions are HOSTED GREEN; no Windows routing change or atomic-publication claim follows.
The separately approved Windows owned npm publication
change routes Project v8–v10 npm/Web filesystem effects through semaprax-full
and the existing held-handle platform authority. Standalone Windows publication
rejects before output effects; inline carriers and generated bytes are unchanged.
The private route requires an existing parent and an admitted ASCII output leaf.
Its source-drift, no-clobber and settlement evidence is implemented.
The owned-data Rust package uses manifest
semaprax.native-rust-owned-data-sdk.v1. It binds the same canonical API
descriptor and exact generated package/provider inventories. It is distinct
from, and does not reinterpret, the existing scalar Rust SDK manifest. The
safe package must build locked and offline without repository source or a
workspace dependency. Unsafe FFI remains quarantined outside the root
semaprax crate and outside the generated safe API.
The lower builder shares the scalar SDK's compiled-ABI admission: five supported GNU/Linux, Apple/macOS, and x86-64 MSVC/Windows target identities, without substituting another libc or ABI. Unsupported targets retain the existing tool error before staging; v8/v9/v10 descriptors and supported-target package bytes are unchanged by this selection rule.
Generated Cargo build-script path boundary
The shared private build-script renderer for v8, v9, and v10 validates
CARGO_MANIFEST_DIR before printing any Cargo instruction. After the existing
target-mismatch check, it requires a present Unicode path containing neither
CR nor LF. It does not canonicalize, require existence, or reject spaces and
other ordinary Unicode characters. Accepted paths retain the exact three
archive-change, native-search, and static-link instructions in their original
order. This follows Cargo's line-oriented build-script output contract:
a path must not introduce another instruction line.
This correction intentionally changes generated build.rs bytes and their
manifest integrity bindings, including standalone owned-data evidence packages.
It does not change descriptors, provider C/archive bytes, generated safe/FFI
Rust, public signatures, package schemas, or the existing scalar SDK. Missing,
non-Unicode, and CR/LF paths fail before any stdout; target mismatch retains
precedence and its original message.
The lower package's build_script::tests renders both families for all five
target identities and authors standalone build-script subprocess checks for
the current host. The two executables are reused across valid-path, CR/LF,
missing-variable, target-precedence, and platform-specific non-Unicode cases.
The implemented release regression corpus is HOSTED GREEN. They test the generated instruction boundary, not
Cargo's downstream execution, archive linking, pathname authority, or a build
sandbox; the separate real package consumers remain required.
Focused gate (reproducible regression selector):
cargo test --locked -p semaprax-native-rust-owned-data-package build_script::tests
Safe Rust thread-confinement gate
The generated NativeRustOwnedDataSdk remains !Send and !Sync; owning a
copied host result does not grant permission to move or share its provider
context across threads. The compile-only lower-package test
tests::auto_traits::generated_owned_sdks_reject_send_and_sync_in_external_safe_consumers
protects this existing boundary for standalone v8, Project v8, v9 and v10.
Each case replays its canonical descriptor fixture and compiles the actual
generated SDK and private FFI into a separate metadata crate. A healthy external
consumer with #![forbid(unsafe_code)] must compile before separate concrete
Send and Sync assertions are checked. Rejections must carry E0277 at the
intended SDK assertion, with the requested trait and SDK identified by compiler
diagnostic facts; a missing dependency, syntax failure or arbitrary nonzero
exit is not evidence. The private FFI is not included beneath the consumer's
unsafe prohibition. No provider or linker is invoked, and these descriptor
fixtures are not evidence of root-owned HIR admission.
The gate contains four healthy consumers and eight negative consumers. It adds no unsafe implementation, dependency, public type or runtime behavior; compile-time confinement is not runtime reentrancy, lifecycle, provider-thread safety or minimum-version validation. All four profiles pass their healthy and negative consumers locally on Linux AArch64/Rust 1.88 and macOS AArch64/Rust 1.98. Strict lower-package library/test Clippy also passes on macOS. The separate generated-SDK Rust 1.85.1 checks below extend compiler evidence without claiming Windows execution.
Focused command:
cargo test --locked --offline -p semaprax-native-rust-owned-data-package --lib auto_traits
Descriptor-selected private Rust helpers
The private FFI renderer emits result-owner declarations only when an admitted
selected result uses them. Scalar-only standalone/v8/v10 selections omit
Handle, RawCall, owner extern declarations, copying/discard methods and the
owner guard. Context initialization, thread confinement, invocation guards,
checked close and reinitialization remain unconditional. Scalar results still
cannot escape an unsettled provider context.
Every v8/v10 owned result retains the discard path for malformed successful
carriers. Flat v9 always needs copying and its owner guard, but emits discard
only when any selected record contains a Bool field: an invalid successful Bool
must drop that record's live owner before reporting adapter rejection. A Bool
parameter alone does not require this result-cleanup path.
This corrects unconditional unused helper emission, not a compiler warning policy. No lint is suppressed and no valid descriptor is rejected. Generated private FFI and dependent manifest bindings intentionally change for scalar-only standalone/v8/v10 and Bool-free v9 selections. Public Rust types, descriptors, provider C/archive bytes, ABI, schemas and capacity limits are unchanged. Previously used helpers preserve their exact emitted bytes.
tests::strict_sources checks all three scalar result kinds in standalone v8,
Project v8 and Project v10: nine separately replayed SDKs and nine external safe
consumers compile metadata with -D warnings. The four-profile thread-confinement
gate also denies warnings in generated SDK and consumer compilation. The flat
descriptor regression includes a Bool in only the later export; the existing
hostile ABI-double gate still checks malformed-Bool owner disposal and checked
context closure at O0/O2. These are compiler/protocol checks, not provider proof.
All 49 lower-package library tests pass locally on Linux AArch64/Rust 1.88 and macOS AArch64/Rust 1.98; strict lower library/test Clippy passes on macOS. The same Rust-1.88-built harness also passes all 49 cases in the cached Linux Rust 1.85.1 image, where fresh generated SDK, external metadata consumer and hostile ABI-double subprocess compilations use that older compiler. The harness itself is not built by Rust 1.85.1; this does not lower the repository MSRV.
Actual Linux AArch64 v8/v9 mixed-borrow packages generated by Rust 1.88/Clang 14
also pass locked/offline Cargo consumers under Rust/Cargo 1.85.1, with
RUSTFLAGS=-Dwarnings. Before this correction the identical strict v9 consumer
failed on unused discard; after regeneration both consumers pass. The
twenty-file handoff contains only the two seven-file SDKs and each consumer's
manifest, lockfile and source; inventories and hashes match before and after
read-only consumption. Comparing before/after publications, only v9 private FFI
and its manifest binding differ; all v8 files and both provider archives match.
The older image does not build the repository or invoke SEMAPRAX. This is
Rust 1.85.1 evidence, not exact 1.85.0, repository MSRV, Windows or hosted evidence.
Raw Wasm call boundary
The raw Wasm owned-result call shape is profile-specific:
(parameters..., result_out: i32) -> status: i32
The adapter validates alignment and the complete result-out range before
semantic execution. It writes one authenticated carrier only after semantic
success and cleanup-plan result publication. Status and out-of-band adapter
failure remain distinct from a successful language Result::Err.
The authored raw-Wasm correction excludes the complete reachable private shadow-stack interval, not merely the wrapper's temporary output. The shared validated-HIR call index and the actual lowerer's frame sizes derive the maximum simultaneous call-path extent for selected exports only. Missing, cyclic, overflowing, or over-capacity selected extents reject; unrelated declarations do not change this admission. Full and partial overlap guards run before UTF-8 imports or semantic execution and preserve the fixed borrowed and public-result scratch reservation. This shared v8/v9/v10 correction intentionally changes their Wasm bytes and dependent artifact bindings, without changing descriptors, public call signatures, or v1-v7 artifacts. Its real-engine poison, nested-helper, settlement, and re-entry regressions are implemented.
Compatibility
The shared checked usize multiplication correction
is an explicit correctness exception to the artifact-byte preservation below:
Wasm modules emitting this operation and their derived integrity bindings change
across affected profiles, not just v8. It restores multiplication by zero and
preserves genuine overflow cleanup; schemas, source semantics, descriptors and
native code are unchanged. Its cross-target regressions are included in the v0.4.0 hosted-green regression corpus.
Project v8 and every protocol above are additive. Project v1–v7 parsing, diagnostic selection, canonical manifest bytes, linked meaning, generated artifacts, npm carrier schemas and bytes, Rust SDK v1 schemas and bytes, scalar Web exports, command packages, and target known answers must remain unchanged.
The v8 implementation must be reachability- and profile-gated. When Project v8 is absent, it emits no owned-data descriptor, metadata, helper, arena/provider operation, target branch, artifact, or runtime state. Earlier schemas reject the new profile, and v8 rejects all earlier profile names. There is no migration that silently rewrites an earlier manifest as v8.
Stable-ID display rename compatibility requires the same selected identity, signature, descriptor semantics, host API identity, and generated consumer behavior before and after rename. A signature, ownership, effect, contract, import, or stable-ID change is not a display rename and must reject or produce a separately reviewed compatibility change.
Completion gates
This implementation may be described as locally evidenced only when all applicable gates below pass at the same commit. Completion-matrix or public promotion additionally requires the exact hosted gate in item 12. Authored but unexecuted repository tests do not satisfy either condition.
- Parser and canonical manifest: exact v8 assignment/order/LF/profile acceptance; every malformed, capacity, ordering, schema/profile-confusion, source-count, and export-count rejection; byte-for-byte v1–v7 manifest and diagnostic preservation.
- HIR admission: success for every admitted parameter/result type and their mixed 0–8-parameter signatures; rejection of every exact exclusion; stable-ID selection, non-entry, monomorphic, effect/import/contract-free, acyclic closure, 256-function bound, and hostile-HIR validation.
- Descriptor replay: canonical bytes and digest; zero-export rejection; one and 32 exports; zero, one, and 8 parameters; strict ordering and uniqueness; display rename; revision/graph binding; independent replay; byte mutation, truncation, insertion, deletion, foreign-subject, unknown-tag, and budget rejection; one descriptor driving every target generator.
- Interpreter/native/Wasm equivalence: the same source corpus produces
equal scalar, byte,
Option, and language-Resultvalues and normalized failures through interpreter, native O0/O2, and Core-Wasm, including empty, embedded-NUL, invalid-UTF-8,0xff,None,Some,Ok, and minimum/zero/ maximumErr(i64)cases. - JavaScript and TypeScript consumption: compiler-free installed package
use; exact declarations and result union; stable-ID access; string and byte
input validation; snapshot isolation; repeated calls; digest and metadata
authentication; ordinary fresh
Uint8Arrayresults; no raw carrier access; locked offline pack/install. - Safe Rust consumption: exact descriptor/manifest replay; generated API
with unsafe forbidden; locked offline external consumer; exact
Vec<u8>,Option, inner languageResult, and outer call-error behavior; no raw handle/context; panic containment; O0/O2 equality. - Hostile carriers: malformed Wasm/provider/artifact digest; invalid or unaligned result pointer; zero, stale, foreign, or duplicate handle/token; wrong length; invalid tag; inactive forged payload; tag/liveness mismatch; wrong destination length; double consume/drop; provider copy/drop failure; arena/provider non-settlement; tampered re-digested metadata.
- Cleanup exactness: independent cleanup-plan replay and target traces for success, pre-publication failure, post-staging failure, inactive cases, postcondition failure, copy failure, settlement failure, repeated entry, token/handle rotation, first-failure stickiness, exact-once active-owner settlement, and no partial result publication.
- Stable-ID display rename: a multi-module fixture is built and consumed before and after a display-only rename; Project graph facts, canonical API identity, npm and Rust method identity, and consumer behavior remain bound to the unchanged stable ID, while presentation facts may change.
- Capacity boundaries: minus-one, exact, and plus-one cases for 32 exports, 8 parameters, 256 linked functions, 65,536 cumulative borrowed input bytes, 65,536 owned output bytes, every descriptor/carrier byte budget, Wasm result storage, native destination length, and handle/arena capacity.
- Compatibility preservation: known-answer bytes for every Project v1–v7 manifest, existing npm carrier, scalar and useful-data Web artifact, command package, and scalar Rust SDK remain exact; profile-absent builds contain no v8 runtime or metadata; all earlier mismatch diagnostics remain stable.
- Cross-platform hosted promotion: all focused gates, hostile tests, external JS/TypeScript and Rust consumers, native O0/O2, browser execution, sanitizers, deterministic inventories, and compatibility KATs pass on one exact commit in blocking Linux, macOS, and Windows jobs, with every claimed browser/runtime and minimum-Rust-version lane named by the release gate. Skipped, cancelled, diagnostic-only, retried, or allowed-failure jobs do not count.
The v0.2.0 tag contains the Project v8 implementation behind its exact manifest/profile and CLI routes, and the tag workflow executed its nonignored regression inventory. That does not satisfy every separately provisioned part of the twelve-gate contract or make either generated package a published, supported SDK. Formal completion-matrix promotion therefore remains an explicit decision after the remaining gates.
The frame-payload product's authored binding fixtures now reopen each real baseline/display-renamed Project revision and replay the exact descriptor from both generated packages against that subject. They compare regenerated npm artifacts and independently reconstruct the native manifest's canonical inventory and descriptor/provider-source bindings from reopened bytes. This is a test-specific manifest observation, not a newly exposed package verifier or an independent proof of the archive's machine-code semantics.
The lower native package builder preserves the safe platform facade's
archive settlement state before projecting its
existing publication error. An Uncertain failure stops before owned-stage
discard, later authority rechecks, or outer package publication. The inert
stage remains for reconciliation; ordinary held handles are still released.
Settled failures retain exact-inventory cleanup and sticky primary-error
precedence. This shared boundary also serves the additive v9/v10 packages.
Private regressions inject closed archive failures and exercise real held-stage
inventory preservation, including foreign bytes. Their release coverage is HOSTED GREEN, but injected archive failures do not
prove physical archiver settlement or process quiescence.
The seven-file outer package has the same one-way publication boundary:
exact-inventory cleanup is available only during preparation. Starting
settle_for_publish consumes that cleanup authority, including when settlement,
rename, or a later path/replay check fails. Failures retain the inert or
published tree for reconciliation; moving a published tree back to its former
staging name cannot restore deletion authority. Private held-filesystem
regressions cover preparation cleanup, retained post-transition stages, a real
no-clobber collision, and Unix post-rename displacement back to the stage name.
Their release coverage is HOSTED GREEN without establishing hostile
same-principal isolation or permanent pathname binding.
The same retained HIR supplies the interpreter and native O0/O2 corpus checks. A separate raw-Wasm ABI observer uses the unchanged production arena/core templates, observes actual mint/drop/copy-out and empty settlement, and checks alignment rejection before imports with preserved poisoned output. It is an independent consumer, not an independent arena implementation or a complete internal destruction trace. These frame-product lanes passed locally on macOS arm64 with Rust 1.98, Apple Clang 21 and Node 24.3, including the actual baseline/display-renamed Project npm and locked/offline Rust consumers.
The frame-payload native corpus additionally has a separate allocator-observed
O0/O2 lane, alongside the unchanged plain-provider lane. The test wraps the
exact generated provider with the existing calibrated allocator observer and
checks each call: nonempty payload allocation and release, empty-owner
free(NULL), allocation-free inactive None/Err, exact copy-out, and stale
drop rejection without another free. Both live-pointer and provider-slot
inventories must be empty between calls. Existing callers select the isolated
module and both authenticated baseline/display-renamed Project subjects.
The observer and its static context are private fixtures, not generated hooks
or public ABI. These checks passed in the same local macOS frame-product run;
successful handle-drop statuses alone are not physical deallocation evidence,
and this lane does not replace sanitizers, OOM handling, or the separate
generated Rust consumer.
The explicitly selected native_execution sanitizer gate reuses those exact
plain-provider and allocator-observed C corpora at O0/O2 for the isolated
module and both retained Project subjects. It requires an absolute
SEMAPRAX_FRAME_SANITIZER_CLANG, enables ASan and UBSan with recovery disabled,
and rejects missing compile-time instrumentation. Independent use-after-free
and signed-overflow controls must fail with their sanitizer diagnostics at
both optimization levels before the 12 product executables may pass. It does
not modify the ordinary compiler flags, provider bytes, or corpus expectations.
SEMAPRAX_FRAME_SANITIZER_CLANG=/absolute/path/to/clang cargo test --locked --offline -p semaprax --test frame_payload_product_v1 native_execution::isolated_and_retained_project_corpora_pass_asan_and_ubsan_at_o0_and_o2 -- --ignored --exact
Provision the selected compiler's headers and sanitizer runtimes. Direct Apple
Clang also needs the installed macOS SDK selected through SDKROOT. This gate
is not sanitizer coverage of every source program, Rust allocation, or public
SDK build, and cannot promote a platform without its other required gates.
The selected gate passed locally on macOS arm64 with Rust 1.98/Apple Clang 21 and on Linux arm64 kernel 6.12.72 with Rust 1.88/Clang 14.0.6. Linux execution used an offline Docker container with all capabilities dropped and read-only source/registry mounts. The four calibration failures were expected controls; all 12 product executables succeeded. Linux compilation also emitted an existing unused-constant warning in the standalone String emitter; no clean Linux lint or complete quality-gate result is claimed here.
The separate frame-format supplement in
tests/frame_payload_product_v1/adversarial.json retains the existing corpus
schema without changing any of the three committed nine-case corpora. Its 72
rows cover every bit of the four-byte declared length, valid power-of-two
payload sizes, all incomplete header lengths with good and bad magic prefixes,
complete-header magic/error precedence, and unsigned 32-bit declaration edges.
Expected validity and errors are literal fixture facts, checked by a separate
host-side inventory oracle rather than by the SEMAPRAX decoder. In particular,
ignoring either upper length byte must no longer pass the conformance corpus.
The original native/raw-Wasm checkpoints run before the supplement. The 72
additional cases make 160 calls with 48 nonempty owned results, and reuse the
existing native executables and raw-Wasm instance. Actual baseline and renamed
Project subjects also use the same published npm/Rust packages and unchanged
external consumer source. The additional Rust consumer has a fresh source/input
path and shares only the compilation cache, avoiding reliance on timestamps
for an in-place include_str! input change. The provisioned Chromium fixture
passes the test-owned supplement to the unchanged same-origin corpus runner
after checking the original host-served corpus; it does not require a changed
host corpus or claim authentication of Project source derivation. The local
macOS frame-product run passed these additional interpreter/native/Wasm/npm/Rust
checks. A separate local Chromium run with Playwright 1.62.0 passed both
packages' nine canonical and 72 supplemental cases; pinned served bytes were
unchanged afterward. These are not Windows or hosted promotion results.
The provisioned private toolchain gate project_owned_tuple_sdk_v1 adds real
published v8/v9 Rust consumers for one borrowed UTF-8 string plus two borrowed
byte slices. It checks cumulative 65,535/65,536/65,537-byte tuples, Unicode byte
length rather than character count, unused arguments, and v8 inactive
None/Err branches. Accepted cases include maximum Some/Ok outputs;
rejections are followed by successful calls on the same SDK object. Separate
objects, input/output mutation, and retained outputs after object drop check
host-owned copies. Each seven-file package is reopened against its canonical
descriptor and regenerated provider binding before the locked/offline consumer
runs. The gate is ignored by default and must be explicitly selected after
tool provisioning; scoped local results are recorded below:
cargo test --locked -p semaprax-toolchain --test project_owned_tuple_sdk_v1 -- --ignored
This is consumer-level capacity and ownership evidence, not an invocation-entry counter, allocation trace, or proof of persistent native-context reuse. It does not replace the separate sanitizer, browser, or exact-head promotion gates.
The npm counterpart tests/project/owned_tuple_npm.rs derives both real
Project subjects and reopens each six-file publication against its verified
inline carrier and descriptor. Its Node consumer spells the same tuple corpus
independently, checks exact variant/record results, and retains independent
copies across two runtime objects. A test-only wrapper counts entry into the
actual selected Wasm exports: accepted calls calibrate one entry, and rejected
tuples must leave the count unchanged before a successful recovery call. This
observes JavaScript preflight before selected-export entry, not Wasm-internal
allocation, native-context lifetime, browser execution, or TypeScript checking.
The scoped local descriptor/lifecycle batch records this fixture's Linux and
macOS execution in Owned npm invocation.
tests/native/owned_tuple_admission.rs uses the same authenticated Project
subjects to generate the actual native v8/v9 providers. Its separate C fixture
observes the provider's existing post-validation invocation counter, owner
slots, issuance serial, and instrumented malloc/calloc/free call counts.
Successful calls calibrate entry and allocation observations; oversized tuples
and malformed UTF-8 must preserve output sentinels and context bytes without
entry, allocation calls, or ownership changes, including inactive v8 branches.
Recovery uses the same physical context. Empty active Bytes results still own
a handle; their drop observes free(NULL) without a payload allocation. This
test-only allocator instrumentation is not a public
ABI, an OOM-recovery proof, or a sanitizer substitute.
The native tuple test passes all four v8/v9 O0/O2 executables on Linux
AArch64/Rust 1.88/Clang 14 and macOS AArch64/Rust 1.98/Apple Clang 21. On those
same hosts, the explicitly selected Rust consumer gate passes actual v8/v9
publication, exact seven-file reopening and both locked/offline consumers.
Linux publication uses the container's /tmp tmpfs and the held
/usr/bin/aarch64-linux-gnu-ar; macOS requires /usr/bin/libtool, as frozen by
the native archive contract. A first macOS invocation selecting ar correctly
rejected with SPX-I234 before package publication; the provisioned libtool
invocation passed without changing admission.
The lower package's three close-selected unit tests also pass on both hosts,
including generated v8/v10 and flat-record boundary consumers at O0/O2 and the
deliberately broken-close calibration. Their hostile provider is a Rust ABI
double, not the real C provider or a proof of panic traversal across C.
All subprocess gates run under external deadlines; Linux also has container
resource/network confinement. The separate strict Rust 1.85.1 package handoff
is recorded above. The exact v0.2.0 tag matrix at
5f6fb9655fdec92c57ab71615cfd7bfa8cc76051 supplies current hosted,
cross-platform nonignored regression coverage; see the
release evidence. Exact Rust
1.85.0, every opt-in sanitizer/tuple corpus, generated-crate registry
publication, and formal public profile support remain separate. No public
support promotion follows from the prerelease.
The same lower-package boundary harness additionally covers joint host unwind
and finalizer failure. Modes 28 and 29 inject a Rust panic immediately after
the private owner guard is armed, outside every extern "C" call. The ABI
double records and flushes the actual std::thread::panicking() state inside
the owner/context finalizers. An owner-drop failure must end after that one
drop; a context-close failure after successful owner drop must end after that
one close. Exact ordered transcripts forbid length/copy, repeated cleanup,
reinitialization, caught-call completion, or outward publication. The healthy
unwind case remains mandatory, and every harness/control explicitly compiles
with panic=unwind at O0 and O2.
Independent generated-test-file controls suppress only one finalizer's abort
response at a time. Ignoring owner-drop uncertainty reaches the still-checked
context close and must fail the same oracle for a forbidden later effect;
ignoring context-close failure reaches the flushed caller-completion witness
and must fail that oracle even when the harness subsequently panics. The
original ordinary-error broken-close control remains. A separate pure mutation
test rejects missing, duplicated, reordered and extra transcript events. This
is generated Rust/ABI-double protocol evidence, not real C-provider cleanup,
physical allocator accounting, panic traversal across FFI, OOM recovery,
panic=abort recovery, or protection against hostile native machine code.
Historical scoped validation of that joint-failure batch passed all 50 lower-package unit
tests on Linux AArch64/Rust 1.88 and macOS AArch64/Rust 1.98. The two new modes
run across five owned result shapes (Bytes, Option<Bytes>,
Result<Bytes, i64>, UTF-8, and the flat record), at both optimization levels:
twenty joint-failure invocations per host, with four additional broken-finalizer
control invocations. The same Rust-1.88-built test executable also passes all
50 tests inside the cached Linux Rust 1.85.1 environment, compiling and executing
fresh generated SDK and control crates there. This is not a Rust-1.85 build of
the root compiler, exact Rust 1.85.0 evidence, or a real C-provider MSRV gate.
All runs have external deadlines; the Linux environments have no network,
read-only input mounts, and bounded resources. Scoped macOS package Clippy and
the two documentation tests pass. The existing frame-product suite also passes
on both hosts after retaining its exact original browser provisioning command
and adding an independently pinned variant command: nine tests pass, while the
three explicitly provisioned TypeScript/sanitizer/npm-installation tests were
not selected. Those counts do not describe Windows or unselected gates. The implemented
release corpus has the current hosted-green baseline; historical executions
retain their actual selected scope.
The complete existing
project_v8_npm_and_rust_routes_run_the_same_corpus_before_and_after_display_rename
frame-product gate also passes on Linux AArch64/Rust 1.88/Clang 14/Node 24.3 at
held parent f725377. It binds actual npm and Rust publications to their retained
descriptors/providers and executes the baseline/renamed nine-case corpus and
72-case supplement across interpreter, native O0/O2, raw Wasm and consumers.
This direct-consumer run is not npm installation, TypeScript, browser or
current-hosted-head evidence.
A separate explicit handoff gate now authenticates those same baseline and
display-renamed products with the current Linux AArch64/Rust 1.88 compiler,
copies only the two verified seven-file SDKs and four unchanged four-file
consumers into a fixed 30-file transfer inventory, and rechecks every source
and transferred byte. An independent compiler-free Linux AArch64 environment
then passes all four canonical/supplemental consumers under Rust/Cargo 1.85.1
with --locked --offline, a read-only handoff and registry, no checkout mount,
no network and a fresh target. The four stdout markers are exact, stderr is
empty, and all 30 files remain byte-identical afterward. The publisher still
runs on its authenticated native scratch filesystem; transfer uses create_new
only after product verification, avoiding unsupported bind-mount publication
semantics without weakening publication checks. This is local generated-package
and consumer evidence, not a Rust-1.85 compiler build, exact Rust 1.85.0,
Windows, hosted, published-SDK or repository-MSRV evidence.
The provisioned Owned Data Browser v1 fixture
imports two actual generated packages in the existing three browser projects,
with mandatory distinct same-origin URLs and an exact twelve-artifact request
inventory. The original four-export direct-Bytes Project is unchanged. A separate
two-export Project stages Bytes before Option/Result selection, preserving
the existing G410 combined-module and G172 owned-return import boundaries.
Separate compiler-side carrier tests bind both fixtures' signatures and verify
unconditional variant staging in typed HIR. Browser cases cover capacity,
nonzero-offset views, calibrated shrinking/regrowing resizable views, exact
hostile-input diagnostics, retained copy independence, both Wasm authentication
failures before instantiation, and same-instance recovery. The variant facade
executes 96 active/inactive/recovery calls plus four oversized rejection/recovery
pairs. Required shared/resizable/transfer features fail closed when unavailable.
Both compiler tests pass locally on Linux Rust 1.88 and macOS Rust 1.98. Actual
CLI publications passed a local Chromium-only run with cached Playwright 1.62.0
and Chromium 151.0.7922.34, using unchanged test/config copies and retained input
bytes. That is not the pinned Playwright 1.55.0 three-browser gate, whose separately provisioned execution cannot be inferred from this local
witness. Firefox/WebKit breadth, raw-carrier faults and physical cleanup traces
retain their own selected-gate requirements. The implemented release corpus has
the current hosted-green baseline. No production, schema, dependency
or support-status changes follow from extending this evidence fixture.
Offline installed-package gate
tests/frame_payload_product_v1/npm_installation.rs adds an explicitly
provisioned v8 gate for both baseline and display-renamed frame projects. It
publishes the real six-file package, checks it against the retained verified
inline carrier, and runs offline npm pack. An independent SHA-512 of the
actual tarball must match both the pack report and the local dependency's
integrity in a closed, two-package-row lockfile before offline npm ci.
The lockfile must remain unchanged and all six installed files must equal the
retained compiler artifacts.
The consumer imports the installed package by name, resolves its exported Wasm
and metadata assets, and runs the unchanged nine-case corpus and 72-case
supplement. Strict TypeScript accepts the same package-name import and rejects
wrong argument types and unguarded Result access. Provision NODE as an
absolute Node executable, NPM_CLI as an absolute npm-cli.js, and TSC_CLI
as an absolute TypeScript 5.8.3 tsc.js; invoking both JavaScript tools through
Node avoids platform-specific command shims. The existing full-toolchain build
prerequisites also apply, including Windows native Cargo/linker provisioning.
cargo test --locked -p semaprax --test frame_payload_product_v1 npm_installation::installed_owned_npm_package_resolves_and_runs_without_compiler -- --ignored --exact
Missing tools fail this selected gate instead of skipping it. Installation and consumption follow package generation without invoking SEMAPRAX or a native compiler; TypeScript is used separately for declaration checking. Offline npm flags, disabled lifecycle scripts, private cache and cleared npm configuration are not OS-level network confinement. This gate passed locally on macOS arm64 with Node 24.3, npm 11.4.2 and TypeScript 5.8.3, for both display names. The separate direct-consumer strict TypeScript gate also passed. The gates cover v8 only and do not establish registry publication or hosted promotion.
Authored same-source Result-extrema gates
tests/support/owned_result_product.rs supplies one canonical two-source v8
Project to the interpreter/native/npm fixture and the private Rust SDK fixture.
Its single stable-ID export returns Err(0), Err(i64::MIN) and
Err(i64::MAX) for three input lengths, successful copied Bytes for two
others, and a genuine division failure after staging Bytes for a sixth.
The extrema stay exact integers; JavaScript expectations use decimal strings
converted to BigInt, never JSON numbers.
tests/project/owned_result_extrema.rs checks the retained Project HIR in
the reference interpreter, actual native providers at O0/O2, and the real
six-file npm publication. The native and raw-Wasm observations distinguish
successful Err status/tag/payload bits from invocation failure, calibrate real
owner allocation/consumption, and require untouched failure outputs and
recovery on the same native context or Wasm instance. Native language failure
is normalized to status 1; the interpreter and raw Wasm retain division status
4. Interpreter cleanup events describe boundary copy-out, not a physical
allocator trace. Provision Clang and Node plus the existing full-toolchain
prerequisites for Windows npm publication:
cargo test --locked -p semaprax --test project owned_result_extrema::same_source_result_extrema_match_interpreter_native_and_npm -- --exact
crates/semaprax-toolchain/tests/project_owned_result_extrema_sdk_v1.rs
publishes the same source through the real Rust builder and reopens all seven
files. It checks the retained descriptor, all parsed manifest facts, inventory
hashes and regenerated provider-source binding before running a separately
locked/offline, unsafe-forbidden Rust consumer. That consumer distinguishes
Ok(Err(...)) from an outer CallError::SemanticFailure, reuses two SDK
objects, and retains independent output vectors after both objects are
dropped. This is not a new package verifier or evidence that an SDK object
retains one physical native context. Provision absolute CLANG and
SEMAPRAX_ARCHIVER, native Cargo, and the existing Windows MSVC environment:
cargo test --locked -p semaprax-toolchain --test project_owned_result_extrema_sdk_v1 provisioned_result_extrema_publish_and_run -- --ignored --exact
Both gates passed locally on macOS arm64 with Rust 1.98, Apple Clang 21 and
Node 24.3, including the explicitly selected, locked/offline Rust SDK consumer.
They add no production ABI, schema, artifact or completion-status change and
do not replace sanitizer or exact-head hosted evidence.
The interpreter/native/npm gate additionally passes on Linux AArch64 with
Rust 1.88, Clang 14 and Node 24.3 at held parent f5cdcc7; that run did not
execute this Result-extrema Rust SDK consumer.
Initialized-owner inactive results
The shared tests/support/owned_inactive_product.rs preserves the exact earlier
inactive-cleanup Project, canonical source/Graph round-trip and manifest. Both
exports initialize Bytes before returning either an active owned value or
successful None/Err(-7). This differs from frame/extrema fixtures whose
inactive constructors allocate nothing.
tests/project_owned_inactive_cleanup_v1 now derives the actual native provider
from the same retained Project and descriptor as its unchanged npm consumer.
The native companion wraps that exact provider with the independently calibrated
allocator observer, then executes O0/O2 with strict C warnings. Its 96 calls
cover both variants and empty, binary/invalid-UTF8, 65,535 and 65,536-byte inputs,
with active/inactive/three-byte recovery sequences on one physical context.
Immediately after an inactive call returns, before host len/copy/drop or context
close, its allocation must already be freed, its pointer and slot inventories
must be empty, and no public handle may have been issued. Empty Bytes separately
requires one free(NULL) call, not a fictitious payload allocation.
Active controls retain exactly one handle, preserve copied bytes and the output canary, settle once, and reject a second drop without another free. The corpus requires 64 active results, 32 inactive results, 80 physical allocations and 96 finalizer calls; final context closure must add no allocation or free. These observations prove caller-visible settlement timing for this source, not every intermediate store, OOM behavior or sanitizer coverage.
The private toolchain's project_owned_inactive_cleanup_sdk_v1 separately
publishes that same Project as a real seven-file Rust package. The existing
tuple package's exact inventory/manifest oracle is shared without changing its
facts or format. Descriptor and regenerated provider-source bindings are checked
before a locked/offline, unsafe-forbidden consumer makes 192 calls using two SDK
objects. It distinguishes successful None/Err(-7) from outer call failure,
checks exact active/recovery bytes, and retains 128 independent outputs through
input mutation and SDK destruction. Package and source bytes are reopened after
consumption. This safe consumer is not itself an allocator trace or proof that
one SDK object retains a single physical provider context.
Focused gates (external deadlines/resource bounds remain required):
cargo test --locked --offline -p semaprax --test project owned_inactive_cleanup::
cargo test --locked --offline -p semaprax-toolchain --test project_owned_inactive_cleanup_sdk_v1 provisioned_inactive_cleanup_publish_and_run -- --ignored --exact
The first gate requires Node and Clang; the explicitly selected SDK gate requires
absolute CLANG and SEMAPRAX_ARCHIVER, native Cargo and the existing Windows
MSVC prerequisites. It must not be counted when left ignored. No source language,
runtime, descriptor, ABI, generated artifact or public-support change follows
from these test-only additions.
The native/npm gate and explicitly selected new SDK gate pass locally on Linux AArch64/Rust 1.88/Clang 14/Node 24.3 and macOS AArch64/Rust 1.98/Apple Clang 21/Node 24.3. The existing v8/v9 tuple SDK gate also passes on both hosts after the shared-oracle extraction. Scoped root/compiler and changed-toolchain-test Clippy passes on macOS. This batch does not execute the new source on Windows, Rust 1.85, real browsers or sanitizers, and does not run the full quality profile or exact-head hosted promotion. In particular, the single-Slice owned-data interpreter gate used by that earlier fixture did not accept its additional Bool parameter. The later retained-Project evaluator below closes that reference-lane gap without changing the original single-Slice entry point or its diagnostics.
Mixed-parameter arity gates
tests/support/owned_mixed_arity_product.rs supplies one canonical v8 Project
with nine selected exports, covering every arity from zero through eight. The
parameter prefix repeats i64, bool, borrow str, and borrow Slice<u8>;
distinct scalar values and borrowed lengths distinguish both positions of each
repeated type. Each export returns owned ok or bad bytes according to its
present arguments. Result bytes are copied from named local fixed arrays,
preserving the language's exact storage-place requirement for borrowed views.
Consumer literals are independent of the source predicates.
ProjectRevision::evaluate_public_api_v1 is the authority-free reference lane
for this complete v8 signature surface. It independently replays the retained
canonical descriptor, requires exact selected-export membership, and validates
argument count, type and order before calling the crate-private HIR evaluator.
The evaluator admits only the four v8 parameter types and six v8 result types,
requires an explicit stable identity and a bounded effect-free, contract-free,
acyclic closure, and snapshots borrowed UTF-8 and byte slices before starting
the fixed-stack worker. UTF-8 contributes its encoded byte length to the same
65,536-byte cumulative borrowed-input limit. Active Bytes payloads use the
existing authenticated copy-out and settlement path; scalar and inactive
variant results create no cleanup event. The retained descriptor, rather than
caller-supplied metadata or discoverable HIR membership, remains the export
authority.
tests/project/owned_mixed_arity_interpreter.rs executes arities zero through
eight, repeated same-type position swaps, all four argument and six result
shapes, scalar/error extrema, None/Some, Ok/Err, language failure and
exact active-owner cleanup. It also checks cumulative UTF-8-plus-slice sizes of
65,535, 65,536 and 65,537 bytes, exact wrong-count/type/order diagnostics, and
an explicit retained function that is absent from the selected descriptor. The
four focused cases pass locally on macOS arm64; this is not cross-backend,
Windows, minimum-Rust, hosted or support-promotion evidence.
The descriptor fixture tests/projections/public_api_descriptor/mixed_arity.rs checks
exact parameter order, names, identities, ordinals, result types and replay,
including separate seven/eight-parameter selections. A selected ninth parameter
must yield the exact SPX-J113 arity diagnostic. The real nine-parameter Project
must reject before exposing an authenticated callback and preserve its input
files. This callback check is not a physical tool-execution counter.
tests/project/owned_mixed_arity.rs retains the same Project descriptor for
actual native providers at O0/O2 and a verified, published six-file npm package.
Independent C and Node consumers exercise every arity, wrong-value controls for
each present position, same-type argument swaps and healthy recovery. The native
fixture separately observes owned allocation/copy/drop and empty context slots;
Node checks host-copy independence across runtime objects. These tests establish
only their observed argument positions and lengths when executed, not general
evaluation order, complete borrowed-content equivalence or browser support.
The private toolchain's project_owned_mixed_arity_sdk_v1 gate publishes the
same Project through the real Rust builder, reopens the exact seven-file package
and binds its descriptor and provider source. An unsafe-forbidden, locked/offline
external consumer calls all nine methods, checks each eight-argument mutation
and recovery, and retains independent outputs across two SDK objects and after
their disposal. SDK object reuse is not proof of one persistent native context.
Focused gates:
cargo test --locked -p semaprax --test projections public_api_descriptor::mixed_arity
cargo test --locked -p semaprax --test project owned_mixed_arity_interpreter::
cargo test --locked -p semaprax --test project owned_mixed_arity::
cargo test --locked -p semaprax-toolchain --test project_owned_mixed_arity_sdk_v1 provisioned_mixed_arity_publish_and_run -- --ignored --exact
All three gates passed locally on macOS arm64 with Rust 1.98, Apple Clang 21
and Node 24.3 after correcting the fixture's invalid string-literal byte view.
The complete descriptor test binary passed all 15 tests; the native/npm and
explicitly selected Rust SDK gates each passed their product test. This is
local evidence, not Windows, minimum-Rust, browser, sanitizer or hosted
validation. A later root native/npm run also passes on Linux AArch64/Rust 1.88,
Clang 14 and Node 24.3 at held parent f5cdcc7; that execution did not include
the mixed-arity Rust SDK consumer.
Native/npm execution requires Clang and Node, plus the existing full-toolchain
prerequisites for Windows npm publication. The selected Rust gate requires
absolute CLANG and SEMAPRAX_ARCHIVER, native Cargo and the existing Windows
MSVC environment. Missing prerequisites fail; no test silently skips. These
fixtures leave bounded temporary evidence trees for inspection. They do not
change production code, generated artifacts, schemas or completion status, and
do not replace strict TypeScript, installed-package, sanitizer or exact-head
hosted gates.
Authentic descriptor capacity regressions
The export-count regression in tests/projections/public_api_descriptor.rs resolves
33 real export declarations. Selections of 31 and 32 derive and replay; selecting
all 33 requires SPX-J113 with the exact export-count diagnostic. The previous
negative selected a nonexistent extra identity, which could conceal a broken
count guard behind a different rejection.
The companion tests/projections/public_api_descriptor/limits.rs changes each of the six
literal wire limits by minus one and plus one, independently for v8 and v10.
All 24 submissions retain canonical member order and have freshly recomputed,
profile-specific digests. Healthy self-replay brackets the mutations; rejection
must identify invalid limits rather than a stale digest or unrelated subject.
These are descriptor validation checks, not execution at the runtime capacities.
All 16 descriptor tests pass in the scoped local batch
on macOS/Rust 1.98 and Linux/Rust 1.88; the exact counts remain historical and formal public promotion is separate
from the current hosted-green release baseline.
Owned-output capacity evidence boundary
The current admitted byte-operation vocabulary has no concatenation or growth
operation: bytes_copy preserves the source extent, ranges cannot enlarge it,
and admitted external or fixed-array roots are bounded by 65,536 bytes. The
selected v10 closure also rejects compiler-owned String intrinsics. This audit
establishes no admitted source construction of a 65,537-byte owned result.
Keep the three observations separate: a real compiled copy can return 65,536
bytes; a 65,537-byte borrowed input rejects before entry; and a test-mutated
65,537-byte output carrier rejects after entry and poisons the facade. The
last observation in project_owned_failure_fsm_v1/result.mjs exercises the
real decoder, not compiler production of an oversized value. None of these
labels relaxes the output bound or grants the full capacity/promotion gate.
Nonclaims
Public Owned Data API v1 does not claim public records or authored variants, nested algebraic data, resources, owned inputs, borrowed outputs, owned UTF-8 strings, mutable/shared values, multiple returns, general generics, lifetime inference, zero-copy transfer, allocator interoperability, callbacks, imports, effects, contracts, async, reentrancy, threads, shared memory, memory growth, WIT/Component Model support, C/C++/Swift/Kotlin bindings, native executable support for Project v8, package resolution, registry publication, signing, provenance, or general public aggregate ABI stability.