Libertas source annotation reference
This is the canonical detailed reference for public source annotations accepted by the current Libertas schema parsers. Use only the canonical spellings shown here. Compiler acceptance alone does not establish supported schema syntax.
The codebot kit carries an exhaustive compact projection of this reference. This page owns the detail; the projection exists to minimize routine App-generation context.
The language parser owns source spelling, native name and constant resolution, and extraction. Studio's shared validator owns placement, effective host type, value grammar, conflicts, protocol reachability, and other portable semantics. The placement column below states the public authoring placement; it is not permission to move an annotation merely because a parser can preserve it for a later Studio error.
Read the App contract first. Use the TypeScript or Rust guide for project structure, and follow each row's topic link for the complete behavior and value vocabulary. Every annotated declaration and nested schema-visible node must also follow the schema documentation invariants, including the user-friendly label/description, member, variant, and List-item rules.
AI Import and the Hub supply value-representation hints
from semantic attributes, and send declared answer labels;
the Hub also renders FormattedText results.
Source comments supply domain meaning without duplicating those generated notes.
Rows marked "compiled into the Display Template" are presentation attributes:
Studio validates them, compiles them into the package's
Display Template as its lowest-specificity
rules, and omits them from the final schema. A display.json rule can change
their effect per device without editing source.
This catalog exhausts schema-parser annotations, not unrelated SDK runtime
functions or serialization derives such as LibertasAvroEncode,
LibertasAvroDecode, VariantIndex, or variant_index!; those remain covered
by the public SDK and the language guides.
Package, discovery, and parser helpers
| TypeScript canonical source | Rust canonical source | Public placement | Result and meaning | Details |
|---|---|---|---|---|
/// @LibertasDefaultLocale("en-US") |
//! #[libertas_default_locale("en-US")] |
Leading package/crate documentation in the selected entry file | Emits package DefaultLocale. Omission means en; all extracted source documentation supplies this locale's default document. |
Documentation and localization |
/// @LibertasTypesOnly |
//! #[libertas_types_only] |
Leading package/crate documentation | Emits TypesOnly=true. The package has no App functions and publishes every non-ignored exact-name public root type. |
Project and discovery rules |
/// @LibertasStringResources(NAME) |
//! #[libertas_string_resources(NAME)] |
Leading package/crate documentation | Resolves exactly one package-owned LMF1 catalog and emits its sorted keys as StringResources. The identifier is positional and unquoted. |
String resources and formatted output |
@LibertasIgnored |
Exact outer-rustdoc line /// #[libertas_ignored] |
Public function or public named type | Omits the declaration as a schema root. A published declaration may not reach an ignored type. It takes no arguments. | Project and discovery rules |
@LibertasExport |
#[libertas_export] on a public function; #[derive(LibertasExport)] on a schema struct/enum |
Parser/compiler helper | Enables the language's public App wrapper or helper attributes. It emits no portable Export attribute and does not replace the native public/export requirement. |
TypeScript guide, Rust guide |
| Not applicable | Exact Union rustdoc line /// #[libertas_export(content = "payload")] |
Rust Union declaration | Emits parser-owned UnionContentName representation metadata. Do not invent tag or untagged forms. |
Rust guide |
File-leading /** @LibertasConstEnum */ |
Not applicable | Dedicated TypeScript file containing one documented exported numeric constant per statement | Treats the constants as members of the numeric Enumeration exposed by a documented exported typeof namespace-import alias in the App entry module. |
TypeScript enumerations |
Function-level task declarations
| TypeScript canonical source | Rust canonical source | Public placement | Result and meaning | Details |
|---|---|---|---|---|
@LibertasSingleton |
#[libertas_singleton] |
Public App function | Emits Singleton=true; at most one task for that App function may exist on a Hub. |
Functions, permissions, and singleton tasks |
@LibertasDataErrorStatus |
#[libertas_data_error_status] |
Public App function | Enables checked Data API status returns; omission keeps Hub-owned termination. | Data failure contract |
@LibertasPermissions(NAME) |
#[libertas_permissions(NAME)] |
Public App function, or a server Endpoint field | Resolves one positional constant containing permissions and emits Permissions. Function permissions require nonempty same-key package string-resource reasons. Server Endpoint permissions are downstream requirements. |
Function and Endpoint permissions |
@LibertasAccessHost("api.example.com,{network_access_local}") |
#[libertas_access_host("api.example.com,{network_access_local}")] |
Public App function only | Emits AccessHost. Every concrete DNS name or reserved local/external grant requires a nonempty same-key package string-resource reason. TCP and UDP are otherwise denied. |
App network access contract |
@LibertasDataSchema(key=DataKey,value=StoredData) |
#[libertas_data_schema(key = DataKey, value = StoredData)] |
Public App function only | Requires exactly one key and one value Union reference and emits FunctionDataSchema=key=DataKey,value=StoredData. Both references resolve locally or to external App FQNs. Studio marks the value Union LibertasData=true. Both languages associate persistence on the function; ordinary native Union declarations remain unchanged. A bare @LibertasDataSchema on a Union is unsupported; neither language uses a standalone Union marker. |
Persistent data schemas |
@LibertasValidationRules('expression : "KEY";') |
#[libertas_validation_rules(r#"expression : "KEY";"#)] |
Public App function, or any schema data node (including fields, variants, and named types) | Emits semantic ValidationRules; field-local, inherited-field, and referenced named-type rules are cumulative and do not replace final structural/mandatory checks. Every pure Boolean expression uses expression : "KEY"; with a quoted package StringResources error-message key. A function rule sees one synthetic Table containing all arguments. The language includes typed first-non-null fallback and no general truthiness. FinalOnly=true; or FinalOnly=false; is an optional leading directive inside this string, never a separate annotation; omission means false (incremental and final). |
ValidationRules |
No other portable schema attribute is public on a function. In particular, field presentation, protocol-role, chart, and Matter annotations do not become function annotations.
Persistent-data Union declaration
Use the DataSchema entry in function-level task declarations. The persistent-data contract gives the complete usage rules.
Defaults, constraints, and ordinary presentation
| TypeScript canonical source | Rust canonical source | Public placement | Result and meaning | Details |
|---|---|---|---|---|
@LibertasDefault(value) |
#[libertas_default(value)] |
Schema data field/type | Emits editable initial Default data; on a Nullable field the reserved $null is the null default for every type, written #[libertas_default($null)] in Rust (an unquoted None on an Option<T> field is a parser error; a quoted "None" is the word; reserved Default values); in Rust $NAME names a crate const (constant references); includes explicit User/List<User> identity selectors and, on a Union field, the native name of the variant initialization selects. On an Endpoint client, the value instead recommends a developer-package::function task process when no eligible server is installed. |
User and group defaults, Common field metadata, Declaring an Endpoint |
@LibertasFixed(value) |
#[libertas_fixed(value)] |
Schema data field/type | Emits one fixed encoded value. On an Endpoint client, the value instead is a developer-package::function task-process identity: the Endpoint selector remains editable, compatible servers are restricted to that process, and its package becomes a dependency. Endpoint Fixed cannot coexist with Default. Native enum declarations generate member fixed values; Union declarations generate separate Discriminator values. On LibertasUser, Fixed is a Hub-enforced security constraint; only current-user is valid, at a request root or within nested request values outside Lists, optionally Hidden. |
Schema attributes, Declaring an Endpoint |
@LibertasNumber(type=u32, min=..., max=..., step=...) |
#[libertas_number(min=..., max=..., step=...)] on a concrete numeric type |
Number or DateTime field/type | Emits NumberType and numeric constraints. Unquoted min/max values emit NumberMin/NumberMax; quoted Data Validation expressions emit RangeMin/RangeMax, including current-row bounds such as max="[^/maximum]" under the dynamic range contract. step remains fixed; in Rust min, max and step accept a $NAME constant reference. TypeScript requires type=: u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f32, or f64. DateTime requires u64. Rust derives type from its native declaration and does not accept a public type= parameter. Integer step defaults to 1 when omitted. |
Type model, TypeScript annotations, Rust annotations |
@LibertasSize(min=..., max=...) |
#[libertas_size(min=..., max=...)] |
String, Bytes, or List field/type | Emits inclusive nonnegative SizeMin/SizeMax (Rust bounds accept a $NAME constant reference): List element count, ordinary value String UTF-8 byte count, or Bytes byte count. Keys use static UTF-8/raw byte bounds; explicit equal bounds select exact bytes under the key rules. Empty values have size zero; nullable null is handled separately. Tables are not valid hosts. |
Common field metadata |
@LibertasPattern("pattern") or @LibertasPattern($CONST) |
#[libertas_pattern(r"pattern")] or #[libertas_pattern($CONST)] |
Effective String field, list element, or named type, including nullable String | Emits Pattern; full-string Unicode scalar matching, with no trimming or conversion. TypeScript uses one JSON double-quoted literal or a native String constant; Rust uses one native cooked/raw String literal or String constant. Studio owns shared semantics. |
Patterns and complete escape rules |
@LibertasUnique or @LibertasUnique(level) |
#[libertas_unique] or #[libertas_unique(level)] |
Scalar field inside one or more ancestor Lists | Emits Unique; omitted level means 99, and a positive level selects the ancestor List scope. |
Common field metadata |
@LibertasUnordered |
#[libertas_unordered] |
List field/type | Emits Unordered=true; List order has no semantic meaning. |
Common field metadata |
@LibertasAskOnAdd |
#[libertas_ask_on_add] |
Field with a value of its own in a List member Table, or a List whose member has one | Emits AskOnAdd=true; the person's Add asks this value first, in a platform-built step, and adds no member without it. Commonly paired with a template lock. |
Add-time values |
@LibertasSuppressLabel |
#[libertas_suppress_label] |
Scalar, struct, or Union field/type; List field/type whose member is a Table | Compiled into the Display Template as suppress_label: omit the selected row’s visual label while preserving its value and controls; on a List omit the List-contributed member name and position, preserving its own heading. |
Label-free value rows |
@LibertasFoldable(initially_open=true) |
#[libertas_foldable(initially_open = true)] |
Table, Union, or List type or field | Compiled into the Display Template as fold. Allows manual folding; unmarked containers remain expanded. The optional initially_open is true (the default), false, which starts the value collapsed without disabling folding, or "nondefault", which starts it collapsed unless its value differs from its default. |
Folding |
@LibertasInlineChoices |
#[libertas_inline_choices] |
Enumeration or Union field or type declaration; not a Bitflags catalog | Compiled into the Display Template as inline. Clients show the permitted choices inline as radio controls after ConstrainedBy filtering, arranged by the inline-choice ladder; a Union with a data-carrying branch stands one per line, its selected payload directly below its chosen choice. A marker on either the field or its type enables it. |
Inline choices |
@LibertasUIIncludeDescription |
#[libertas_ui_include_description] |
Schema data field/type | Compiled into the Display Template as include_description. Clients show the localized long description inline together with the short display name for that UI node. It does not change data or wire encoding. |
Common field metadata |
@LibertasReadOnly |
#[libertas_read_only] |
Schema data field/type | Emits ReadOnly=true; clients present the value but do not offer ordinary editing. Every non-user writer (initialization, CopyFrom, EditRequest, calculation or link-return CopyTo, draft restoration) still writes it. |
Common field metadata |
@LibertasHidden |
#[libertas_hidden] |
Schema data field/type | Emits Hidden=true; the field remains typed transaction/context data but is hidden from ordinary visualization and editing. |
Common field metadata |
@LibertasTimeInterval |
#[libertas_time_interval] |
Numeric field/type | Emits TimeInterval=true; the raw number is a duration in seconds. |
Date and time |
@LibertasDateOnly |
#[libertas_date_only] |
Explicit integer Number field/type | Emits DateOnly=true; every value is a valid decimal Gregorian yyyyMMdd, never an epoch or timezone conversion. |
Date and time |
@LibertasFormat("#,##0.00") |
#[libertas_format("#,##0.00")] |
Number, DateOnly, DateTime, or TimeOnly field/type | Compiled into the Display Template as format: one programming-language-neutral Unicode LDML pattern; it changes display only. |
Display formats |
@LibertasMoney("USD", 2) |
#[libertas_money("USD", 2)] |
Signed i64 Number field/type |
Declares exact integer minor units, explicit currency and fixed scale; enables localized currency display and inline entry. | Money |
@LibertasPhysicalUnit("millimeter-per-day") |
#[libertas_physical_unit("millimeter-per-day")] |
Number field/type | Emits a canonical CLDR core PhysicalUnit; it declares the supplied unit and performs no conversion. |
Physical units |
@LibertasBitflags or @LibertasBitflags(Access) |
#[libertas_bitflags] or #[libertas_bitflags(Access)] |
Bitflag catalog declaration, or integer field selecting that catalog | Emits Bitflags=true on the Enumeration catalog or Bitflags=Access on an ordinary integer. Values remain integer masks. |
Bitflags, TypeScript Bitflags, Rust Bitflags |
@LibertasEnum(A, B, C) |
#[libertas_enum(A, B, C)] |
Applicable String alias/field or Enumeration declaration supported by that language | Defines a catalog using positional members. The parsers currently cannot attach source documentation to those fabricated members, so codebots must use a documented native numeric enum instead and must not generate this otherwise public compatibility form. TypeScript values=[...] is not canonical syntax. |
TypeScript enumerations, Rust attributes |
@LibertasEnumSource("$.choices") |
#[libertas_enum_source("$.choices")] |
Unsigned integer field/type; the key's String or integer type when the target List declares a key; or a List of that type | Emits EnumSource; the host stores the zero-based index of an item in the resolved same-tree List or, when that List's member declares a Key field, the chosen member's key value. A stored value matching no current member is unanswered and never remapped. An unanswered non-Nullable host whose source offers exactly one selectable member takes that member. A List host stores several distinct chosen indices or keys. |
Common field metadata, EnumSource keys, EnumSource List hosts |
@LibertasKey |
#[libertas_key] |
Exactly one direct non-Nullable String or integer Number field of a Table used only as a List member; the field also carries Unique and may be Hidden |
Emits Key=true. An EnumSource host targeting that List stores the member's key instead of its index and must have the key's type. Uniqueness comes from the required Unique; a List without a key keeps index storage, and stored values are never migrated. |
EnumSource keys |
@LibertasFormattedText |
#[libertas_formatted_text] |
Statically ReadOnly schema data node with effective Bytes type | Emits FormattedText=true. The canonical LMF1 tuple follows the owning contract's static placement, request-value sources, and runtime-use restrictions. |
String resources and formatted output |
@LibertasMimeTypes("image/png,image/jpeg") |
#[libertas_mime_types("image/png,image/jpeg")] |
Bytes field or named type outside CacheIdentity | Emits a MIME filter for the LMB1 Bytes contract. Its source grammar, content-size behavior, and incompatibility with FormattedText are validated by Studio. | MIME-aware Bytes annotation |
@LibertasLLMDocTrans(instruction="...", validation="@.facts", doc_type="image/*", accept_multiple_inputs=true) |
#[libertas_llm_doc_trans(instruction = "...", validation = "@.facts", doc_type = "image/*", accept_multiple_inputs = true)] |
Named Table struct declaration used in an editable Request or SubscriptionRequest | Declares one per-occurrence document action. Instruction is required; validation path, MIME filter, and multiple-file choice are optional. Direct marked children select scalar or nested composite results, excluding Hidden and Fixed subtrees. A Table whose variants are all LLMDocTrans is a classifier: it sorts several files into the enclosed forms and imports each with its own declaration; validation and multiple-file choice are invalid on it. |
Document Schema authoring, categorized import |
@LibertasLLMDocField or @LibertasLLMDocField(allowEmpty=false) |
#[libertas_llm_doc_field] or #[libertas_llm_doc_field(allow_empty = false)] |
Direct result child of an LLMDocTrans Table, or a field within a selected composite | Selects any supported Libertas value, including complete nested Tables, Lists and Unions; nested scalar markers override blank conversion. Non-Nullable Number defaults allowEmpty to true; other values default false. True requires a typed Schema Default (a variant name on a Union) and a string projection, mapping exact "" to that Default. blank=VALUE (Rust blank = VALUE) instead declares the value exact "" applies, spelled as a Default literal: $null on a Nullable field, 0, or a Union variant such as ShortTerm; it is invalid with allowEmpty. A Union imports a variant's payload fields only when marked; with none marked in any variant it imports the variant name alone. An unchanged variant keeps its payload; a new one, including a blank variant, is initialized as an editor choice, required unmarked fields left unanswered. |
Complete conversion contract, declared blank value |
@LibertasConstrainedBy("$.allowed_choices") |
#[libertas_constrained_by("$.allowed_choices")] |
Enumeration or Union request field; Response variant | A hidden integer list, at a root path or (field form) a parent-relative ^ or typed ancestor ^<Type> path such as a row's own sibling, constrains field choices or the response NextRequest actions; the list is written by CopyFrom, EditRequest, or a calculation or link-return CopyTo, never by the user. |
Backend-constrained choices |
@LibertasActionControl("sections") |
#[libertas_action_control("sections")] |
Hidden direct integer-list field of a displayed Response or SubscriptionData payload with NextRequest | Declares a named control whose current Request membership is the field's original protocol Union discriminants; Actions restricts the built-in button. An empty array hides its control, and malformed arrays reject the update. |
Named action controls |
@LibertasCopyFrom("$.first,$.fallback") |
#[libertas_copy_from("$.first,$.fallback")] |
Protocol Request/SubscriptionRequest data | Emits source paths under the shared copy rules; the context table selects the reference context and grammar. | Shared CopyFrom and CopyTo rules |
@LibertasRangeMin("expression") |
#[libertas_range_min("expression")] |
Number or DateTime field/type | Emits RangeMin; one Data Validation bound expression compatible with the host type supplies an inclusive live lower bound for GUI and final validation. Incompatible result types are errors; null means no bound. |
Dynamic numeric ranges |
@LibertasRangeMax("expression") |
#[libertas_range_max("expression")] |
Number or DateTime field/type | Emits RangeMax; one Data Validation bound expression compatible with the host type supplies an inclusive live upper bound for GUI and final validation. Incompatible result types are errors; null means no bound. |
Dynamic numeric ranges |
Attribute combinations and inherited effective metadata are validated by Studio. Do not infer that two annotations can coexist merely because they have separate rows in this catalog. The ValidationRules entry also covers data fields, variants, and named types.
Endpoint and protocol annotations
| TypeScript canonical source | Rust canonical source | Public placement | Result and meaning | Details |
|---|---|---|---|---|
@LibertasEndpointSchema(Protocol) |
#[libertas_endpoint_schema(Protocol)] |
LibertasEndpoint field |
Resolves a local or external Union and emits ProtocolSchema. The Endpoint's absence/presence of the server marker determines its side. |
Declaring an Endpoint |
@LibertasEndpointServer |
#[libertas_endpoint_server] |
LibertasEndpoint field |
Emits EndpointServer=true. Without it the Endpoint is a client. |
Declaring an Endpoint |
@LibertasEndpointBaseObjects("$.device,$.room") |
#[libertas_endpoint_base_objects("$.device,$.room")] |
Endpoint field | Emits comma-delimited BaseObjects paths that bind the Endpoint instance to configuration objects. |
Declaring an Endpoint |
@LibertasRequest |
#[libertas_request] |
Protocol Union variant | Emits Request=true for one-shot client-to-server input. |
Protocol roles |
@LibertasResponse |
#[libertas_response] |
Protocol Union variant | Emits Response=true for a correlated server-to-client result. |
Protocol roles |
@LibertasError |
#[libertas_error] |
Protocol Union variant that also has an effective Response role | Emits Error=true; clients handle the response out-of-band of the current state transition, preserve the current interaction, and keep retry available. |
Protocol roles |
@LibertasErrorFieldPath |
#[libertas_error_field_path] |
Nullable String field of an Error-marked Response, at most one per variant | No argument; emits ErrorFieldPath=true. Optionally locates the rejected Request field for marking after the error dialog. |
Error field path |
@LibertasOutputOnly |
#[libertas_output_only] |
Statically ReadOnly field or named type used only in Request payloads; Nullable, String, Bytes or List; no SizeMin above 0 |
No argument; emits OutputOnly=true. Clients skip its validation and send its empty value on Submit; display and copies are unchanged. |
Output-only request fields |
@LibertasSubscriptionRequest |
#[libertas_subscription_request] |
Protocol Union variant | Emits SubscriptionRequest=true for stream establishment or renewal. |
Protocol roles |
@LibertasSubscriptionData |
#[libertas_subscription_data] |
Protocol Union variant | Emits SubscriptionData=true for server-to-client stream data. |
Protocol roles |
@LibertasAccessPrivilege("Read,Write") |
#[libertas_access_privilege("Read,Write")] |
Request or SubscriptionRequest variant | Emits the alternative-access bitmap (Read=1, Write=2, both=3). Omission also means both; mutating operations must explicitly require Write. |
Request access |
@LibertasCalculationRequest("A,B") |
#[libertas_calculation_request("A,B")] |
Protocol request data field | Emits a field's calculation variant list, making the field a trigger of those calculations under the field calculation contract. | Field calculation requests |
@LibertasCalculationRoot("A,B") |
#[libertas_calculation_root("A,B")] |
Root node: any request data field, record type, List member type, Union field or type, or the request's own payload type | Emits {"Name":"CalculationRoot","Value":"A,B"} on the node the named calculations are for, under the calculation root contract. |
Calculation root |
@LibertasCopyTo("@.orderTotal") |
#[libertas_copy_to("@.orderTotal")] |
Successful calculation or link-return Response payload field; reduced SubscriptionData variant in the optional App pattern | Emits destination paths under the shared copy rules. Calculation results, link returns, and reduced subscriptions define application and lifetime. | Shared CopyFrom and CopyTo rules |
@LibertasAppendTo("Entries.entries") |
#[libertas_append_to("Entries.entries")] |
Incoming SubscriptionData root array field | Appends ordered complete elements to one admitted working variant's root array. Preserves duplicates; rejects conflicting writers and invalid resulting values atomically. No name-based replacement for annotated fields, including when another variant is named. Requires an initial snapshot. | Array append |
@LibertasAppendIndex("$.start_index") |
#[libertas_append_index("$.start_index")] |
Same array field as AppendTo | Excludes the referenced control field from ordinary replacement and CopyTo; optional non-null integer report field checks the exact destination length before append, including empty appends; negative/mismatched positions reject the whole report. The App owns ordering, deduplication, retention, and initial snapshots. | Array append |
@LibertasDefaultRequest |
#[libertas_default_request] |
Request variant whose payload needs no user input (Nil, or only hidden/read-only Fixed or Default fields) | Optionally selects the single explicit correlated request for endpoint entry; chart-producing requests are forbidden. | Default entry |
@LibertasNextRequest("A,B") |
#[libertas_next_request("A,B")] |
Protocol Union variant | Emits the allowed next client variant native names as NextRequest. Outside workflows, omission of both NextRequest and WorkflowRequest is a non-transition acknowledgement; workflow completion can be terminal. |
Chaining, caching, and copied values |
@LibertasWorkflowRequest("EditProfile") |
#[libertas_workflow_request("EditProfile")] |
Response variant | Declares the WorkflowRequest semi-role. |
WorkflowRequest semi-role |
@LibertasPrevRequest("ReopenProfile,ReopenAddress") |
#[libertas_prev_request("ReopenProfile,ReopenAddress")] |
Request variant | Lists ordinary Back actions; their CopyFrom source is the current editor and each action must independently validate before sending. Their controls are suppressed in an embedded master-detail trailing pane under the pane contract. | Workflow interactions |
@LibertasLink("OpenTopic", stacked=true) |
#[libertas_link("OpenTopic", stacked = true)] |
Any field; Table, Union, or Enumeration type declaration | Names one same-protocol target, constructed through CopyFrom with the tapped node or host field bound; the field's complete declaration wins over its type's. Optional Boolean stacked defaults to false; omission or false emits exactly {"Name":"Link","Value":"OpenTopic"} and preserves ordinary Request invocation and editor link-return CopyTo. True emits exactly {"Name":"Link","Value":"OpenTopic,stacked=true"}. This upcoming form requires a LinkOnly, fully filled target with no editable input, an ordinary Request with display-only Response replies or a SubscriptionRequest with a live Response snapshot; see the owner for validation, Close, release and lifetime rules. Displayed-value targets must be in that variant's NextRequest; Hidden occurrences are rejected. |
Links |
@LibertasLinkOnly |
#[libertas_link_only] |
Request variant targeted by a declared Link in the same protocol; SubscriptionRequest variant targeted by a stacked Link | Emits LinkOnly=true. The target is offered only through declared links: NextRequest and the filtered action set still govern its link rows, while Actions, menus, endpoint landings, and automatic singleton selection never offer it or count it. Studio rejects it on any other node, on an untargeted variant, with DefaultRequest, and with ExcludeUI. Clients predating the marker keep offering it in Actions. |
Link-only requests |
@LibertasRequestConfirmation |
#[libertas_request_confirmation] |
Request variant | Emits {"Name":"RequestConfirmation","Value":"true"} on the variant, the same marker form as DefaultRequest and LinkOnly. Marks a critical Request: whenever a person's choice or submission is about to send it, the client first shows a dialog naming the action with Send and Cancel, from every entry point and after a popup or an editor is confirmed. Cancel sends nothing. For the AI assistant, the Hub starts the generated tool's description with "Requires user confirmation." and instructs the assistant, in every turn that offers such a tool, to state the action and its values and to call the tool only after the user confirms in a later message; the Hub does not verify the confirmation. Wire form and validation are unchanged; a program calling the endpoint directly is not affected, and the service still validates every request. Studio rejects it on any other node and on a DefaultRequest. |
Critical requests |
@LibertasNextResponse("A,B") |
#[libertas_next_response("A,B")] |
Protocol Union variant | Declares allowed replies on requests, or directional Compatible SubscriptionData on SubscriptionData. | Chaining, caching, and copied values |
@LibertasProtocolVariant("EditWages") |
#[libertas_protocol_variant("EditWages")] |
Ordinary Enumeration member | Associates its typed value with one variant of each consuming Endpoint protocol; no navigation or wire change. | Enum/protocol associations |
@LibertasCacheIdentity |
#[libertas_cache_identity] |
Direct field of a Request root record | Enables large-page draft recovery using all marked fields as immutable identity; optional app-maintained protocol revision invalidates older drafts. Small requests omit it. | Workflow draft identity |
@LibertasExcludeUI |
#[libertas_exclude_ui] |
Endpoint server field carrying a resolved ProtocolSchema, or reachable protocol Request/SubscriptionRequest variant |
Emits ExcludeUI=true; Hub Control omits the server from its UI-device list and LLM tool collection, while generated Control GUI and Hub LLM tool-definition generation omit the operation. Admin, protocol, routing, and wire behavior remain complete. All servers sharing one resolved ProtocolSchema root must use the same value. |
Declaring an Endpoint |
@LibertasAINavigationPrompt("NAVIGATION_PROMPT") |
#[libertas_ai_navigation_prompt("NAVIGATION_PROMPT")] |
Protocol Union or page-defining protocol variant | Selects optional App guidance for GoTo Search, or opts another task page into Search, through a nonempty package StringResource. Union guidance precedes page guidance; both contribute. AI selects an offered, fully constructible link or action choice without supplying request fields. | AI Search |
@LibertasLLMToolCall(false) / @LibertasLLMToolCall(true) |
#[libertas_llm_tool_call(false)] / #[libertas_llm_tool_call(true)] |
Protocol Union or descendant Request variant | Controls Hub LLM tool-definition generation. The nearest explicit Boolean value along the Union-to-variant path wins; omission defaults to true. false on a Union excludes its Request variants until a descendant explicitly sets true. It does not change Control UI, protocol messages, or authorization. |
AI tool calls |
@LibertasProtocolConformance("Read & Status") |
#[libertas_protocol_conformance("Read & Status")] |
Protocol Union, or Union-typed protocol variant | Emits ProtocolConformance; client and server expressions independently declare mandatory compatible variants. |
Protocol conformance |
@LibertasDefault/@LibertasFixed and their Rust counterparts have their
Endpoint-client meanings described in the defaults table. Permissions may
also appear on an Endpoint server as described in the function table.
External types, Matter descriptors, and Union metadata
| TypeScript canonical source | Rust canonical source | Public placement | Result and meaning | Details |
|---|---|---|---|---|
@LibertasForeignType("developer-package::Type") |
#[libertas_foreign_type(developer-package::Type)] |
Published top-level compatible named type | Emits ForeignTypeSchema naming its direct official external App type. The compatible type keeps its own identity and explicit attributes override inherited official attributes. |
External types and App dependencies |
@LibertasDeviceType("descriptor") |
#[libertas_device_type("descriptor")] |
Effective LibertasDevice field |
Emits the Studio-generated physical Matter DeviceType descriptor. Do not invent the encoded descriptor manually. |
Matter |
@LibertasVirtualDeviceType("descriptor") |
#[libertas_virtual_device_type("descriptor")] |
Effective LibertasVirtualDevice field |
Emits the Studio-generated VirtualDevice descriptor. Do not invent it manually. |
Matter |
@LibertasDiscriminator("kind") |
Not applicable | TypeScript discriminated Union when automatic detection is ambiguous | Emits parser-owned UnionTagName. Normal TypeScript literal/enum discriminators are detected automatically; Rust uses enum declaration order and native representation. |
Protocol roles |
Two-dimensional chart annotations
| TypeScript canonical source | Rust canonical source | Public placement | Result and meaning | Details |
|---|---|---|---|---|
@LibertasChart(mark) |
#[libertas_chart(mark)] |
Response/SubscriptionData chart payload or composition | Emits a primitive mark or composition as Chart. |
Charts |
@LibertasChartChannel(x, tooltip) |
#[libertas_chart_channel(x, tooltip)] |
Direct chart data field | Emits its canonical ChartChannel roles. |
Charts |
@LibertasChartScale(id=series, kind=linear, ...) |
#[libertas_chart_scale(id = series, kind = linear, ...)] |
Scale-bearing chart data field | Emits ChartScale; source kind is Compiled into the Display Template as the scale hint, and the other properties stay in the schema. |
Charts |
@LibertasChartGuide(target=x, source=scale, ...) |
#[libertas_chart_guide(target = x, source = scale, ...)] |
Explicit guide binding or guide-label field | Emits ChartGuide; target and source are required. position is Compiled into the Display Template as the guide hint. |
Charts |
The complete mark, channel, scale, guide, composition, visible-text, and hidden-context rules are in Presentation and localization and the normative client-side chart specification.
Three-dimensional chart annotations
| TypeScript canonical source | Rust canonical source | Public placement | Result and meaning | Details |
|---|---|---|---|---|
@LibertasChart3D(mark) |
#[libertas_chart3d(mark)] |
3D Response/SubscriptionData chart payload or composition | Emits a 3D primitive mark or composition as Chart3D. |
3D charts |
@LibertasChart3DChannel(x, z, tooltip) |
#[libertas_chart3d_channel(x, z, tooltip)] |
Direct 3D chart data field | Emits canonical Chart3DChannel roles. |
3D charts |
@LibertasChart3DScale(id=series, kind=linear, ...) |
#[libertas_chart3d_scale(id = series, kind = linear, ...)] |
Scale-bearing 3D chart data field | Emits Chart3DScale; source kind is Compiled into the Display Template as the scale hint, and the other properties stay in the schema. |
3D charts |
@LibertasChart3DGuide(target=z, source=scale, ...) |
#[libertas_chart3d_guide(target = z, source = scale, ...)] |
Explicit 3D guide binding or guide-label field | Emits Chart3DGuide. |
3D charts |
@LibertasChart3DView(projection=perspective, ...) |
#[libertas_chart3d_view(projection = perspective, ...)] |
One physical 3D chart scene | Emits Chart3DView camera and projection settings. It does not define a gesture mode. |
3D charts |
The normative geometry, topology, camera, interaction, fallback, and resource rules are in Client-side 3D charting.
Inferred and generated metadata: never invent source annotations
The final schema contains attributes and fields that are inferred from native source or generated from one of the public annotations above. Their presence in schema JSON does not create another public macro or decorator.
| Generated or parser-owned result | Source of the result |
|---|---|
Nullable=true |
TypeScript optional/nullish supported type, or Rust Option<T>. There is no public LibertasNullable annotation. |
Rust NumberType |
Concrete Rust u*, i*, f32, or f64. TypeScript obtains it through LibertasNumber; never write a direct NumberType annotation. |
NumberMin, NumberMax, NumberStep, SizeMin, SizeMax |
Emitted components of the public Number and Size annotations. Their schema names are not source spellings. |
LengthMin, LengthMax |
Retained schema fields from the removed TypeScript String spelling. Current source uses SizeMin/SizeMax through the Size annotation. |
Fixed on enum members; Discriminator on Union members; UnionTagField on a ScriptLanguage-only native tag field (such as TypeScript/Python; never Rust) |
Native enum values and TypeScript discriminated-Union literals. Do not duplicate them with source annotations. |
UnionTagName |
Automatic TypeScript discriminator detection or @LibertasDiscriminator. There is no direct UnionTagName decorator. |
UnionContentName |
The Rust libertas_export(content = "...") rustdoc directive. There is no direct UnionContentName attribute. |
LibertasProtocol=true |
Injected for a Union reached by an Endpoint ProtocolSchema. There is no public LibertasProtocol source marker. |
LibertasData=true |
Injected by Studio for the value Union in a function FunctionDataSchema binding. Both languages use their function-level DataSchema annotation; neither has a public standalone Union marker. |
EnumValues |
Parser metadata produced while constructing an Enumeration from the language's public enum syntax. Do not write it directly. |
FullyQualifiedName and source locations |
Transient parser resolution/diagnostic metadata. Studio removes it before final schema publication. |
AppDependencies |
Studio deployment planning from resolved external App types and Endpoint-client Fixed packages. Never populate it in App source. |
Rust no_std=true |
Native crate attribute #![no_std], not a Libertas helper macro. Use it only when the App and all dependencies support that build model. |
The emitted-name column throughout this document is explanatory. Never derive a
new @Libertas... or #[libertas_...] spelling from a schema JSON property.
Not public or not usable
Codebots must not emit any spelling in this section.
Removed annotations
-
@LibertasStringis removed; use@LibertasSize(min=..., max=...)for String, List, or Bytes bounds. Existing serialized LengthMin/LengthMax values remain recognizable, but are not generated by a current public source annotation. -
@LibertasFunctionDataSchemais removed; use@LibertasDataSchema(key=DataKey,value=Type)on the public function. The old bare Union marker is also removed. Studio owns the generated LibertasData marker; do not rewrite retained schema bytes. -
@LibertasIntegerand@LibertasFloatare removed source spellings. Use the single@LibertasNumber(type=..., min=..., max=..., step=...)annotation. Existing serialized NumberType/NumberMin/NumberMax/NumberStep fields are unchanged; regenerate source artifacts rather than editing retained schemas. -
@LibertasLibraryand#[libertas_library]are recognized only so Studio can report that theLibraryschema attribute was removed. -
@LibertasUseOriginalDocumentand#[libertas_use_original_document]were removed. Published compatible types share the official type document automatically throughForeignType. -
@LibertasExternalNativeTypewas removed. Native external ownership is inferred from resolved language imports and exact-name App exports. -
@LibertasUIHeaderand#[libertas_ui_header](schema attributeTableHeader) were retired, and Studio rejects them with a message that names the replacement: a Display Templatepromoterule selecting the field to promote, with the sameuse_parent_nameoption, or aflattenrule selecting the struct, List, or Union to flatten. -
@LibertasUINameand#[libertas_ui_name]were retired, and Studio rejects them with a message that names the replacement. A data-titled row is a Display Templatelabelrule on the row's struct with its value from apromoterule on a child (data-titled rows).
Unsupported authoring forms
Use the canonical forms in the catalog. In particular:
#[libertas_ignored]belongs on its exact outer-rustdoc line; it is not a standalone SDK macro; see Rust discovery.- TypeScript functions use
@LibertasDataSchema(key=DataKey,value=Type); both named arguments are required, and a bare Union marker is invalid; see the function DataSchema contract. - Use documented native numeric enums. Fabricated annotation members cannot carry required member documentation.
- Named-argument variations do not create additional supported spellings.
Removed Rust SDK helpers
The SDK helper allowlists no longer admit libertas_string, libertas_array,
or libertas_cacheable, because the owning schema parser does not support
those source forms. Use libertas_size for size bounds and the documented
CacheIdentity behavior where needed. libertas_discriminator is also not a
Rust schema annotation; Rust uses native enum representation.
MIME-aware Bytes annotation
Apply @LibertasMimeTypes("image/png,image/jpeg") or
#[libertas_mime_types("image/png,image/jpeg")] to a Bytes field or named type
to restrict its media types. The MIME-aware Bytes contract
defines the filter, LMB1 encoding, valuation, size, copy, and submission rules.
Keep unannotated Bytes fields for raw binary protocols; MimeTypes is a
semantic choice for media values, not a replacement for ordinary Bytes.
CacheIdentity
CacheIdentity opts large workflow requests into persistent local draft recovery.
TypeScript uses @LibertasCacheIdentity; Rust uses #[libertas_cache_identity].
Both emit CacheIdentity=true. Use clients that implement this attribute;
older client binaries do not provide draft recovery.
Eligibility and field placement
-
`CacheIdentity` is a Boolean field attribute. A workflow page is cacheable
only when at least one root-record field has effective
CacheIdentity=true. Use it for large workflow requests where losing completed field edits would require substantial re-entry. Small requests must omit CacheIdentity; clients do not guess eligibility from payload size or field count. - Multiple marked fields form one identity tuple. All must match; they are not alternative identities. The client does not infer identity from field names, Hidden, or CopyFrom.
- Mark only direct fields of the request variant's root record. A referenced record used as that root payload qualifies. Nested record fields, array elements, and fields in selectable Union branches cannot carry the attribute. Studio validates placement for every request use, including referenced types.
- Identity values must be defined after initialization; valid null is allowed and differs from undefined. They remain immutable for the editor lifetime, including against user edits and calculation writes. Restoring editable data preserves the freshly initialized identity values.
Identity, revisions, and application responsibility
Capture the tuple after normal initialization or receipt of EditRequest data, before user editing. Match every marked field by exact typed equality, including null, numeric values, bytes, Union selections/payloads, and array order. The application must supply enough distinguishing context to prevent one workflow's draft from matching another workflow. A workflow identifier is a typical choice.
Recommendation: include an application-maintained data/workflow revision when changes to saved data invalidate earlier drafts. For example, a historical page edit may invalidate later pages; changing their identity revision prevents restoring obsolete local drafts. The client does not infer these dependencies.
Protocol changes are allowed. Application data revisions are independent of protocol/schema versions; tasks need not detect protocol changes. Management tools guard schema compatibility, and clients reject incompatible cached data at restoration. Compatible protocol changes alone do not invalidate drafts.
Optional recommendation: the application may maintain a protocol revision and mark it as another CacheIdentity field. Advancing it guarantees rejection of drafts with the old value even when a protocol change preserves structural compatibility. Maintaining and advancing this revision is entirely the application's choice and responsibility. Workflow revision, protocol revision, or both may be used; the client assigns no special meaning to either field. Without a distinguishing identity change, semantic changes that preserve the schema's structure may remain undetectable.
Draft scope and lifetime
The full cache key comprises Hub identity, task ID, endpoint ID, request variant index, and the complete CacheIdentity tuple, within the authenticated account's storage. The first four components identify the page, not the entire cache key. Different workflow identities and revisions retain separate drafts. Initialize the page first, then look up its complete identity directly; unrelated entries do not need to be scanned or deleted. Garbage collection removes expired drafts.
Persist the latest committed editor state after each change, creating the entry if absent and updating it otherwise. This includes nested fields, array operations, Union selection, null/undefined transitions, and atomic calculation results. Drafts survive process exit and restart. Entries expire one calendar month after their last committed update. Clients collect expired entries at startup and reject expired entries before restoration. Reads and restore prompts do not extend retention. Removing the Hub, task, or endpoint removes its drafts.
Delete a submitted editor's draft only after its successful correlated backend reply. Transport acceptance alone is insufficient. Retain it on transport or backend error. Calculation replies never clear the parent draft.
When offered under the pane contract, the workflow's in-app Go Back action selects a declared PrevRequest and voluntarily abandons the current edit. Delete that editor's draft after the successful correlated, non-error reply to the previous action. Cancelling its chooser, failing validation, or receiving a transport or backend error retains the draft. An explicit editor Close, including Close in the right-hand master-detail pane, deletes that editor's draft when the close is accepted. These actions delete only the departing editor's matching draft; they do not delete a retained leading editor's draft or other workflow identities.
System-level Back by button or gesture, ordinary screen-navigation Back, and process exit or interruption preserve the committed draft for recovery. They are separate from the workflow's Go Back action. Closing a field picker or nested editor returns to its parent and does not discard the parent's draft. The system Close of a stacked-link page likewise releases only that displayed page and preserves the live editor beneath; it is not an explicit editor Close. Navigating away from the stack follows these existing draft rules.
EditRequest does not itself delete a draft. If it is a successful reply to a submission, that correlation still clears the submitted draft. Incoming page initialization then follows the normal identity comparison and restoration rules below.
Restoration and calculations
Initialize the new editor first, including when entered through EditRequest. Look up the entry for its full identity and verify the stored tuple. If it matches, ask whether to restore. Declining removes the cache and keeps fresh initialization. Accepting attempts restoration without submitting the workflow request. Ordinary rerendering or returning from a field picker does not repeat the prompt.
Restoration assigns only the values the user can edit and the destinations that a calculation or a link return writes; a link-return destination cannot be recomputed, so it is restored as saved. Every other Hidden, ReadOnly, or Fixed value, including a cookie and an allowed-set source that no calculation or link return writes, keeps the value the fresh editor supplied; the draft's copy of it is not applied. A restored selection outside the fresh allowed set becomes unanswered under the reset rule and does not discard the draft.
Restore atomically against the current schema; a source that a calculation writes is restored from the draft and recomputed by the seeded calculations. Corrupt encoding or structural/type incompatibility discards the cache and rolls back the entire attempt to the fresh editor. Compatibility includes the declared primitive kind and representation, record fields, List element types and available Union branches; a value of the wrong kind or an invalid encoding is not a restorable draft. Do not partially restore a structurally incompatible draft, coerce incompatible data, or silently omit incompatible fields. An exact schema version match is not required.
For a structurally compatible draft, check each restored node's own value constraints, including numeric bounds evaluated in the current editor and reference context under the range contract. Replace an invalid value through ordinary initialization at that node, including its applicable Default or an unanswered value. A descendant's failure must not reset its containing record, List item or page; preserve every other restored value. A List that itself violates its size constraint is reset at that List. These local resets are part of the atomic restoration and do not discard the compatible draft.
Undefined required fields are legitimate draft state. Preserve undefined separately from null, false, zero, empty values, bytes, and Union selections. A committed empty String is assigned, not undefined; if it violates its own constraint, initialize that String normally, applying its Default when present. Ordinary initialization may leave a value unanswered or still invalid. Cross-field ValidationRules keep their normal evaluation, and final ValidationRules run at Next/Submit; neither resets restored values or discards the compatible draft. Submission stays blocked until the current editor is complete and valid. This local recovery does not permit incomplete or invalid Avro requests or backend persistence of unfinished requests.
After successful restoration, seed calculations once for all current instances, including array items. Reset destinations through ordinary initialization and reevaluate using restored inputs. Use the normal ordered scheduler and dependency propagation; incomplete or invalid requests cannot be sent. Do not restore old in-flight transactions or automatically submit the workflow editor.
General field-edit commitment
Only finished editing commits a user-entered field value. This applies throughout
client editors, not just caching. Intermediate control text neither replaces
the committed value nor triggers calculations or cache updates. Typing - in a
number control therefore does not turn an existing committed number into
undefined. An unassigned field remains undefined until a completed edit assigns
an admissible value.
Submission must resolve the active edit through this same boundary; it cannot silently submit an old value while replacement text remains unfinished. Native controls may use their normal completion actions. Programmatic initialization and atomic calculation updates retain their transaction boundaries.
MIME-aware Bytes in workflow drafts
For a MIME-aware Bytes field, a draft never stores
the media content. It stores a client-local file link when one exists; an
in-memory value received from the server stores only a marker to use the
freshly initialized value after recovery. An explicit clear stores an
undefined marker. The link and its temporary file stay within the client and
are never sent to the Hub. A missing or unreadable link on recovery makes
only that field undefined and reports which field needs a new file; the other
edits restore. If no corresponding fresh value exists for an in-memory marker,
that field is undefined. This is an exception to full-value draft storage,
not a relaxation of identity or schema checks. MimeTypes cannot occur
within a CacheIdentity field because that identity is persisted. A temporary
file remains while an active editor or unexpired draft refers to it and is
automatically removed after its last reference and a cleanup grace period.
NextResponse on SubscriptionData declares Compatible SubscriptionData, rather than correlated replies.