Skip to content

Latest commit

 

History

History
229 lines (191 loc) · 11.6 KB

CELLSCRIPT_PUBLIC_INTERFACES.md

File metadata and controls

229 lines (191 loc) · 11.6 KB

CellScript Public Interfaces And Compatibility

Status: current inferred-facts implementation; final alpha.2 acceptance is pending

Schemas: cellscript-package-interface-v5 (current only), and cellscript-interface-compatibility-v1

What The Interface Represents

Every successful compile now constructs a canonical public package interface. It is stored in compile metadata as public_interface; its CKB BLAKE2b-256 identity is stored as interface_hash.

The interface contains only exported items and records the contracts that a consumer or Registry upgrade must preserve:

  • canonical module, type, constant, action, lock, and function identities;
  • explicit public, public(package), and private visibility;
  • type parameters, phantom parameters, value abilities, and Cell lifecycle capabilities as separate fields;
  • fields, enum variants, fixed layouts, and type identities;
  • callable parameters, source qualifiers, outputs, return types, effects, and entry witness ABI;
  • source generic templates and applied types in exported signatures, without implementation-only monomorphizations;
  • target, VM, witness, lock-args, source-encoding, Spawn/IPC, and compatibility profile identities;
  • the cellscript-ckb-temporal-interface-v1 fixed representation, RFC0017 constructor/decoder inventory, distinct domain names, since_abi, and mechanical migration identity; and
  • generated-builder and deployment-contract hashes.

Edition 2026 keeps the historical public-by-default behavior for an item with no modifier. New reusable packages should spell visibility explicitly so a future edition migration does not silently change the exported surface. The 0.30 line selects restricted dependency-facing value generics and the closed fixed_value profile; the normative syntax, derivation, compatibility, and migration rules are in CellScript Public Value Generics.

On the experimental 0.26b branch, the bounded native Edition 2027 type_script entry lowers to the existing action interface while its semantic foundation separately records the exact type-group<T> trigger. The native lock_script entry likewise lowers to the checked lock interface and records its exact lock-group authorization boundary. The source edition, public interface, core semantics, and entry contract remain distinct identities; see the Edition 2027 preview grammar.

The experimental cellc migrate --to 2027 command does not decide public API compatibility or rewrite visibility. It replaces only the one final legacy entry in a self-contained module, preserves all surrounding source bytes, and requires the old and candidate core semantic identities and ELF bytes to match. Full six-dimensional public-interface comparison remains a later migration gate.

module example::math

public struct Pair<T: fixed_value> {
    left: T
    right: T
}

public(package) fn sum_pair(pair: Pair<u64>) -> u64 {
    return pair.left + pair.right
}

private fn implementation_detail(value: u64) -> u64 {
    return value
}

public(package) items are visible to modules in the same package but are not emitted as dependency-facing exports. private items are local to their module. Imported public generic templates may be specialized across package boundaries; the specialization is generated in the template's owning module and linked by a compiler-internal import. It is never a source-level export.

Edition 2026 compatibility remains public-by-default. When a module mixes an explicit modifier with declarations that still rely on that default, compiler, CLI metadata, and editor diagnostics emit W2500 and list the declarations to classify.

Emit An Interface

For a source file or package:

cellc interface path/to/package
cellc interface path/to/package --json
cellc interface path/to/package --output target/package.interface.json

Without --json or --output, the command prints a compact exported-signature view and abbreviates the exact six-ability profile as fixed_value. The JSON envelope and output file contain both interface and interface_hash, with all constraints expanded. The hash is computed over canonical JSON; reordering source declarations or replacing the expanded profile with its compact source spelling does not change the identity after normalization.

Checked nominal compatibility and declaration identity

The declaration interface and its existing digest retain source type spellings. Renaming a private import alias used by a public field can change the declaration layout/interface digest and the conservative declaration-only comparison. A bare interface JSON document does not establish that two spellings name one owner. Do not infer nominal compatibility from equal offsets, sizes or ELF bytes.

Default native builds retain declaration/owner catalogs when multiple lowered labels refer to one defining nominal declaration or interface handles require an independently checked module projection. Those bindings are required for independent admission even without --source-contracts; the checker still rejects missing or rebound evidence. The flag requests optional complete source-contract export, including constant values. It cannot suppress evidence needed by an executable contract. Ordinary builds without these evidence needs retain the existing compact output.

For alias-independent nominal compatibility, compile both candidates with --source-contracts and retain their complete ELF, metadata, lowering record and source map. Then use:

cellc interface-diff --checked --old old/main.elf --new new/main.elf --json

This mode independently verifies each four-file bundle under bounded reads, then compares the existing qualified checked module projection directionally. The report schema is cellscript-checked-interface-compatibility-v1; it names both contract digests and artifact hashes. Same-owner aliases can agree, while a same-width declaration from a different owner rejects. Missing, malformed, modified or oversized sidecars reject before a compatibility result. Sidecars use the same canonical neighboring paths as verify-artifact.

In JSON mode, a breaking comparison exits with E2501 and emits one diagnostic envelope containing the complete comparison fields. It does not print a report followed by a second JSON document. An explicitly requested output file retains the comparison report. This applies to both declared and checked comparisons.

The result covers the checked projected contracts. It does not establish source behavioral equivalence, deployment, peer execution or authorization. It does not replace package/Registry admission or change exact-hash receipt commitments.

Compare Two Releases

cellc interface-diff \
  --old target/old.interface.json \
  --new path/to/candidate-package \
  --json

The report classifies changes across six independent dimensions:

Dimension Examples of breaking changes
source_api removing an export; changing a type parameter, parameter, return type, or output; tightening a generic constraint
serialized_layout changing fields, variants, offsets, fixed sizes, or type identity
runtime_abi changing an entry ABI, witness placement, target, or versioned VM contract
effects_capabilities increasing inferred facts in any dimension, changing value abilities or Cell lifecycle capabilities
builder changing the generated transaction-builder contract
deployment changing the deployment/runtime identity contract

A breaking report exits with stable compiler code E2501. Additive exports are reported as compatible changes; they still change interface_hash, so a consumer can choose whether it accepts a new exact identity. Relaxing a generic constraint is source-compatible only when the serialized layout, runtime ABI, effects/capabilities, builder, and deployment dimensions remain independently compatible. Changing parameter count, name, order, or phantom status and tightening any constraint are breaking.

Readers require the complete current v5 interface. Old or mixed generations reject and must be rebuilt; there is no default temporal/effect contract or older-interface comparison reader. Callable effects is mandatory: concrete declarations carry canonical context_reads, lifecycle_ops and process_ops; uninstantiated generic templates carry explicit null evidence. Missing evidence is never converted into an empty fact set. Candidate facts must be a subset of required facts independently in every dimension. See the effect contract for evidence and lifecycle boundaries. Changing an exported callable from raw u64 to a temporal domain remains a source/call-ABI break. Registry publication validates current temporal and fact fields instead of trusting an arbitrary interface hash. It also requires the closed value-ability vocabulary in canonical order and the fixed, serializable, non-linear public generic layout boundary.

Registry Admission

CellScript source publication includes the canonical interface and hash in the signed publish payload. The Registry API recomputes the hash, rejects a mismatch, requires monotonically increasing SemVer, and compares a candidate with the greatest predecessor on the same compatibility line. A new major version (or new 0.minor line before 1.0) may intentionally break the old interface; an incompatible change within a line is rejected. The standalone Registry verifier also checks that the stored interface and interface_hash agree. For ELF bundles, the parser-free artifact checker recomputes the public interface hash and validates the expanded public generic record before accepting its typed instantiations.

This is package compatibility evidence, not proof that an artifact is safe or deployed. Registry verification, the typed semantic checker, CKB-VM execution, deployment evidence, and chain commitment remain separate states.

Typed Semantics Relationship

The public interface answers “what can a dependency rely on?” The cellscript-typed-semantics-v11 record answers “what typed operations and control-flow facts were lowered?” Its embedded cellscript-semantic-foundation-v3 additionally answers where values came from, which transaction roles they bind, how Cells are disposed, where claims are enforced, and how entry/artifact contracts are identified. These remain distinct from the package interface hash. Its fixed-Cell binding table records the resolved source, ordinal, local identity and Script-group membership; syntactic parameter sources are not physical selectors or authentication. An explicit policy's tagged export set and outer witness ABI are bound by its entry contract. The package interface hash does not by itself select or prove a particular deployed policy; deployment and builder consumers must retain the selected artifact contract as well. Generic instantiation v2 separately retains the declaration owner, ordered parameter constraints and lowered names. Public declarations are cross-checked against that contract; private and imported instances still undergo argument and binding checks. Those checks do not provide universal template equivalence or a compatible-open deployment receipt. Typed semantics v8 can also name an exact, manifest-declared external verifier under the trusted-external evidence tier. That record binds the selected CellDep data hash and delegation operation; it is not part of the package interface hash and is not a proof of the external program's implementation. ELF builds additionally bind the typed record to the verified lowering and machine records described in CellScript Verified Artifact Boundary.