Skip to main content

Crate cratestack

Crate cratestack 

Source
Expand description

CrateStack server facade for procedures-only, no-database services.

This crate is the db = None slice of the framework (epic #326). It re-exports the shared schema / parser / policy / SQL surface plus the Axum HTTP bindings and the generated Rust client runtime — everything a datasource { provider = "none" } server needs for routing, procedure dispatch, and REST/RPC transport, minus a database backend.

It deliberately does not depend on cratestack-sqlx — not behind a feature flag, genuinely absent from Cargo.toml. datasource { provider = "none" } schemas can never declare a model (enforced at parse time, cratestack#327), and db = Postgres codegen is the only path that ever references sqlx-backed symbols (::cratestack::sqlx::PgPool, the Json<T> sqlx variant, SqlxRuntime, …) — so a facade that structurally never has those symbols to offer can only ever support db = None. A schema compiled with include_server_schema!(schema, db = Postgres) under this crate fails to compile with a single, clear compile_error! (cratestack#347’s guard_server_postgres_backend, in cratestack-macros/src/include/datasource_guard.rs) rather than a wall of unrelated “cannot find sqlx/SqlxRuntime in cratestack” errors — see this crate’s README.md for the exact reproduction and transcript.

For the same reason, this crate also does not depend on cratestack-grpc or prost. transport grpc codegen is entirely model-driven — CRUD routes generated per model block — and procedures are not (yet) wired into the generated gRPC service at all (see crates/cratestack-macros/src/include/server/grpc/mod.rs). Since db = None schemas can never declare a model, a transport grpc schema paired with db = None could only ever produce a gRPC service with zero methods — there is nothing useful gRPC adds here, so the dependency (tonic/prost and everything they pull in) is left out entirely rather than kept around unused. transport rpc and REST (the default) both work fully under db = None — see docs/design/rpc-transport.md and docs/design/no-database-mode.md.

cratestack-pg (with default-features = false to drop its postgres feature) also supports db = None and continues to work — this crate doesn’t replace that path, it just names the “I never touch Postgres” case directly instead of asking a consumer to depend on a crate named for the database backend they’re explicitly opting out of.

Schema macros emit ::cratestack::* paths, so consumers rename this crate via Cargo’s package = field:

[dependencies]
cratestack = { package = "cratestack-api", version = "0.6" }
cratestack::include_server_schema!("schema/foo.cstack", db = None);

See docs/design/no-database-mode.md for the full db = None design and this crate’s README.md for a quick-start.

Re-exports§

pub use async_stream;
pub use chrono;
pub use cratestack_client_rust as client_rust;
pub use futures_util as futures;
pub use regex;
pub use serde;
pub use serde_json;
pub use tracing;
pub use uuid;
pub use cratestack_axum::axum;

Modules§

audit
Audit log primitives.
axum
axum is an HTTP routing and request-handling library that focuses on ergonomics and modularity.
batch
Batch envelope.
context
Request-scoped context: authenticated identity, structured principal, transport extensions, plus the AuthProvider trait that auth middlewares implement.
envelope
Signed envelope (HMAC-SHA-256).
error
CoolError — the framework’s error type, its 4xx/5xx HTTP mapping, and the public response envelope clients see on failure.
events
Model-event bus: typed created/updated/deleted envelopes that procedure handlers can subscribe to.
find_many
Built-in support for the FindMany<Model> procedure-argument type (.cstack syntax) — search-with-filters for procedures. Composes with PageInput rather than absorbing it — a procedure wanting both filtering and pagination declares two arguments, e.g. procedure search(query: FindMany<Post>, page: PageInput): Page<Post>.
headers
Header helpers used by axum-bound handlers: optimistic-locking ETag parsing/emission, W3C traceparent extraction, RFC 7239 Forwarded client-IP extraction, and context enrichment that bundles those.
idempotency
Idempotency-key middleware.
json
Schema-declared Json columns need a model-struct field type that’s the same on every backend so the same struct compiles on server and on embedded (including wasm32-unknown-unknown, which can’t depend on sqlx).
page
Generic paginated-page envelope used by every list route. The shape mirrors what generated clients consume.
projection
query
Query-string parsing for axum-bound handlers: percent-decoded pair extraction and the structured filter expression grammar (?where=...) used by macro-generated list endpoints.
ratelimit
Per-principal rate limiting.
route_naming
Canonical REST route-segment derivation for a model name.
rpc
Runtime primitives for the transport rpc generation style.
rust_keywords
Rust keyword classification, shared by cratestack-parser (schema-time field-name validation) and cratestack-macros (identifier escaping at codegen time) so the two stay in sync — see cratestack#398.
schema
Schema IR — the parsed shape of a .cstack file. Every IR node carries source-span back-pointers so consumers can map errors to positions in the original text.
schema_fingerprint
Drift-detection middleware for the x-cratestack-schema-sha header (issue #178). Every generated client stamps its own SCHEMA_SHA256 constant (SHA-256 of the .cstack source it was compiled against) onto every request; this middleware compares that value against the server’s own constant and tracing::warn!s on a mismatch — nothing more. It never rejects a request: a missing header (a client not yet regenerated) is not itself a warning, and a present-but-different value only ever produces a log line, never an error response. See docs/design/protobuf.md-adjacent context: this grew out of the protobuf/gRPC work but applies to every transport (rest/rpc/grpc alike), since nothing about schema drift is protobuf-specific.
validators
Field-level validators.
value
Backend-agnostic JSON-shaped value used throughout the framework (auth claims, audit payloads, RPC error details, schema config).

Macros§

include_client_schema
HTTP client schema: model/input/procedure stubs for talking to a server over the wire. No DB, no router, no FromRow impls. Renamed from include_client_macro! in 0.3.0.
include_embedded_schema
Embedded ORM schema: rusqlite backend only. Compiles to native and to wasm32-unknown-unknown (via sqlite-wasm-rs). No sqlx, no axum, no procedures. Local apps that don’t need an RPC surface use this.
include_server_schema
Full server schema: sqlx Postgres backend, Cratestack runtime, axum router, procedures, events. Pass db = Postgres (only value currently supported; MySQL / SQLite-via-sqlx will land in a future release).

Structs§

Attribute
AuditActor
AuditEvent
AuthBlock
BatchItemError
Public, safe-to-expose shape of a per-item failure. Mirrors crate::CoolErrorResponse without the optional details field — batch callers asking for per-item detail can repeat the operation singly against the failed item to get the full error envelope.
BatchItemResult
Per-item result inside a BatchResponse. The index is the item’s position in the original request, so clients can pair results with inputs even after server-side reordering (e.g. parallel batch_get fetches in the future).
BatchRequest
Wire envelope for POST /<model>/batch-* request bodies. Holds the items in a single field so the envelope can grow (e.g. a future client_request_id) without breaking deserialization.
BatchResponse
Wire envelope returned by every batch route. Always 200 OK at the HTTP layer; inspect summary.err (or scan results) to surface per-item failures to the user.
BatchSummary
Summary counts attached to every BatchResponse so callers can branch on aggregate status without scanning the result list.
CoalesceExpr
Left-hand operand of a coalesce-based filter — chain a comparator method to turn it into a FilterExpr.
CoalesceFilter
COALESCE(col_a, col_b, ...) <op> <value> — left-hand expression is the first non-null among the listed columns; right-hand side is a bound value via the usual FilterValue envelope. Lets schemas express the “ranked-fallback compare” pattern that shows up in outbox / scheduler tables, where a single row carries several time columns and the dispatcher wants the earliest non-null one.
CodecSet
ConfigBlock
ConfigEntry
CoolAuthIdentity
CoolContext
CoolErrorResponse
CoolEventBus
CoolEventEnvelope
CreateDefault
Datasource
DbErrorInfo
Structured information extracted from a driver-level database error.
EnumDecl
EnumVariant
Field
FieldFilterInput
Every operator a filterable field might support, as one flat optional-per-operator envelope — generated per-model code reads only the operators that make sense for a given field’s type (e.g. a Boolean field’s generated to_filters() never looks at contains). V is the field’s own scalar Rust type (String, i64, bool, chrono::DateTime<Utc>, …) — never Option<V> even for an optional field, since these operators describe a value to compare against, not the field’s own nullability (which is_null covers instead).
FieldRef
Filter
HmacEnvelope
HMAC-SHA-256 backed envelope. Sealed messages are self-describing CBOR maps: signature recipients can decode the envelope, fetch the key by kid, and verify without out-of-band coordination.
InMemoryNonceStore
In-memory nonce store. One mutex; the working set is bounded by the clock-skew window — a 5-minute skew at 10k req/s caps at ~3M entries, which is fine. Production multi-replica deployments swap in Redis.
Json
JsonTextPath
Left-hand operand of a json_get_text filter — chain a comparison method (.eq, .lt, .is_null, …) to produce a FilterExpr.
MixinDecl
Model
ModelColumn
ModelDescriptor
ModelEvent
MulticastAuditSink
Fan an audit event out to multiple sinks. Errors from any individual sink are aggregated into CoolError::Internal so a single failing downstream does not silently swallow problems with the others.
NoEnvelope
Pass-through envelope used when transport-layer signing is not required.
NoopAuditSink
Default sink that does nothing. The in-database audit table is treated as authoritative; downstream consumers are added by wrapping a different sink (or composing several).
OpDescriptor
Wire-shape of a single op in a transport rpc schema. See docs/design/rpc-transport.md for the full design — in short, an op is the dispatch unit shared by every RPC binding (HTTP unary, HTTP batch, HTTP stream, WebSocket). The macro emits one OpDescriptor per CRUD verb and per procedure when Schema.transport == TransportStyle::Rpc.
OrderCatalog
One model’s order-by surface: its own sortable scalar columns ((api_name, sql_column)) and its own to-one relation edges. Exactly one OrderCatalog is emitted per model, regardless of how many distinct relation paths pass through it.
OrderClause
OrderRelationEdge
One to-one relation edge out of a model. target points at the related model’s own catalog so resolve_order_target can keep walking further segments; to-many relations are never represented here (mirroring the codegen’s existing to-one-only walk), so a key that names one simply fails to resolve.
Orderable
Marker for a path whose hops are all to-one, so a scalar at the end of it can be rendered as a correlated subquery and used for ordering.
OwnedSchemaSummary
Page
PageInfo
PageInput
Built-in pagination-input argument type (PageInput in .cstack), currently valid only as a procedure argument — the request-side mirror of Page/PageInfo on the response side. Field names and optionality match PageInfo’s own limit/offset exactly, so a generated list route and a hand-written PageInput-accepting procedure decode the same wire shape.
ParsedIndexAttribute
The parsed shape of an @@index([...], using: ..., opclass: "...") attribute.
PrincipalContext
PrincipalFacet
Procedure
ProcedureArg
ProcedurePolicy
Projection
Result of a .select(...)-projected read. Holds the model with only the selected columns populated — non-selected fields carry their type’s Default::default() value ("" for String, 0 for integers, None for Option<T>, etc.).
ReadPolicy
RelationFilter
RelationHop
One traversed relation edge: the FK linkage plus how the related rows are quantified (ToOne for a plain to-one hop, Some/Every/None for a to-many hop under a quantifier).
RelationInclude
Typed handle for an .include(...) call on a query builder. Carries everything the runtime needs to issue the side-load query for a to-one relation: a function pointer that extracts the FK value from a parent row, and a static descriptor of the related model.
RequestContext
ResolvedOrderTarget
A dotted sort key resolved down to the relation hops to traverse plus the terminal scalar column, ready for crate::order_value_sql.
RouteTransportCapabilities
Wire-level capabilities for one route under a REST binding.
RouteTransportDescriptor
Schema
SchemaError
SchemaSummary
SealedEnvelope
SelectionQuery
SourceSpan
SpatialPoint
Builder returned by crate::point for assembling a spatial filter. Holds nothing but the lat/lng pair until a comparator is chained.
SqlColumnValue
StaticKeyProvider
In-memory KeyProvider for tests and single-tenant deployments. Banks running real workloads bring a backed implementation (KMS, Vault, HSM).
SubscriptionGuard
RAII cleanup for one or more CoolEventBus subscriptions that all share one lifecycle — e.g. the per-operation handlers a single GET /rpc/subscribe/{op_id} connection registers for the duration of its SSE stream (docs/design/rpc-transport.md §3.4a, cratestack#390). Every tracked handle is unsubscribed when the guard drops, whether that’s because the underlying stream ended normally (backpressure overflow) or because it was cancelled mid-poll (an ordinary client disconnect) — both just drop this guard the same way, so cleanup doesn’t need to special-case which one happened. Without this, a long-running server would accumulate one permanently-registered, permanently-a-no-op handler per historical connection — a real unbounded-memory footgun for a public, freely-reconnectable endpoint, not a hypothetical one.
SubscriptionHandle
Opaque token returned by CoolEventBus::subscribe, needed to later remove that exact handler via CoolEventBus::unsubscribe. Fields are private — the only way to obtain one is subscribe, and the only thing it’s good for is passing back to unsubscribe.
TypeDecl
TypeRef
Unorderable
Marker for a path that has crossed a to-many hop. Ordering accessors are not implemented for this marker, which reproduces the old guarantee that asc()/desc() simply did not exist past a to-many relation — a compile error, not a runtime failure.
VectorDistanceExpr
Builder returned by FieldRef::distance_to — chain a comparator (.lt/.lte/.gt/.gte/.eq) for a threshold filter, or .asc/ .desc to use it as an ORDER BY target. The common k-NN “closest first” case is .asc(); see also FieldRef::order_by_distance, sugar for exactly that.
VectorDistanceFilter
<column> <metric op> <query_vector> <cmp> <value> — a distance-to- a-query-vector expression compared against a bound threshold. Built via [super::field_ref_ext]’s FieldRef::distance_to, then a comparator method turns it into a FilterExpr. Mirrors super::CoalesceFilter’s shape: a left-hand computed expression plus a bound right-hand value.
View
ViewDescriptor
ViewSource

Enums§

AuditOperation
BatchItemStatus
Either a successful per-item outcome (Ok) or a per-item failure (Error). Serializes as a tagged enum with the discriminant in status:
ConflictTarget
Conflict target for an upsert. Defaults to the model’s primary key (matching the previous PK-only behavior). Columns lets callers upsert on an arbitrary unique tuple — most commonly a natural key that’s distinct from the PK (e.g. (owner_id, provider) on a per-owner-and-provider settings row, or (pairing_id, slot) on a per-slot envelope).
CoolError
CreateDefaultType
ExtensionKind
An opt-in framework/database capability a schema announces via a top-level extension <name> { } block (cratestack#153). Declaring an extension only unlocks schema-visible syntax for that capability (e.g. @no_rate_limit, the Vector(n) scalar type) — it never gates codegen or runtime behavior by itself; that’s a separate, same-named Cargo feature per consuming crate (cratestack#161, out of scope here).
FilterExpr
FilterOp
JsonFilter
JSON / JSONB filter predicates. Two flavors:
ModelEventKind
NullOrder
Where NULLs sort relative to non-NULL values. PostgreSQL’s default is NULLS LAST for ASC and NULLS FIRST for DESC; SQLite’s default is NULLS FIRST for both. CrateStack pins the framework default to NULLS LAST so listings stay deterministic across backends and so soft-deleted rows (typed Option<DateTime> that surface as None for visible rows) don’t muscle their way to the top of every listing. Override per-clause via OrderClause::nulls_first when scheduler / outbox queries want fresh-as-null tasks at the head of the queue.
OpKind
PolicyExpr
PolicyLiteral
ProcedureKind
ProcedurePolicyExpr
ProcedurePolicyLiteral
ProcedurePredicate
QueryExpr
ReadPredicate
RelationQuantifier
SortDirection
SpatialFilter
PostGIS spatial filter primitives. v1 ships two ops that cover the “is point inside this zone” / “is this point within radius of that zone” cases — the rest of the ST_* surface can land on demand.
SqlValue
TransactionIsolation
Transaction isolation level requested by a procedure via @isolation(...). Mirrors the PostgreSQL spec: lower variants tolerate more anomalies, higher ones cost more under contention. Banks running multi-row updates (transfers, postings) typically pick Serializable and pair it with retry-on-serialization-failure.
TransportStyle
Wire-shape the schema generates for. Picked once per schema (via the top-level transport rest|rpc directive) so generated servers and clients only carry one binding’s worth of surface.
TypeArity
Value
VectorMetric
Distance metric for a Vector(n) similarity search (see docs/design/extensions.md §6/§7, cratestack#163). Maps 1:1 onto pgvector’s three distance operators and the opclass names used by @@index([...], opclass: "...") (cratestack#156’s DDL) — but is never inferred from an index: an index is only ever an optional access-path speedup, and AC #2 on cratestack#163 requires distance ordering/filtering to keep working with no vector index present at all (a plain sequential scan), so callers state the metric explicitly at the call site. VectorMetric::from_opclass is a convenience for callers that already know their index’s opclass and don’t want to duplicate the mapping by hand — it is never called automatically.

Constants§

BATCH_MAX_ITEMS
Default upper bound on items in a single batch request. Server backends enforce this before any SQL runs and surface CoolError::Validation on the outer Result when exceeded. The cap is identical for all five batch operations; deviating per-op would invite footguns where batch_get accepts a list that batch_create of the same length rejects.
CBOR_SEQUENCE_CONTENT_TYPE
MAX_LIST_LIMIT
Hard ceiling on the limit query parameter (REST) / RPC list-input field every generated list route accepts, regardless of whether the model is @@paged. Requests above this are rejected with a 400, the same way negative limit/offset already are — see handle_list_<plural>_dispatch in the generated code, shared byte-for-byte between REST and RPC dispatch.

Traits§

AuditSink
Pluggable audit sink. Implementations fan audit events out to downstream systems (Kafka topics, Redis pubsub, HTTP webhooks, S3 buckets) for long-term retention or SIEM ingestion. The in-database audit table written by cratestack_sqlx remains the canonical record; sinks are best-effort projections.
AuthProvider
CoolCodec
CoolEnvelope
CreateModelInput
HttpTransport
IntoColumnName
Anything that can name a single SQL column. Lets coalesce accept both bare &'static str column names and typed FieldRef handles, so callers don’t have to choose between schema-rooted typing and ad-hoc strings at the call site.
IntoSqlValue
KeyProvider
Resolves signing keys by kid (key id). Banks running multi-tenant or rotating keysets implement this so the envelope code never has to know the storage mechanism. Implementations must be constant- time for not-found vs wrong-tenant errors — never use the error message to leak whether a key id exists.
ModelPrimaryKey
Accessor for a model’s primary key. Implemented by the macro on every generated model struct so the batch operations can pair returned rows back to the position of their input PK in the request, producing a BatchItemResult with the right index and a NotFound entry for any requested PK that didn’t come back.
NonceStore
Tracks the nonces of sealed envelopes that have already been verified inside the clock-skew window, so a captured-and-replayed request gets rejected the second time. Banks running multi-replica deployments back this with Redis so the rejection holds cluster-wide.
ProcedureArgs
ProjectionDecoder
ReadSource
Anything a read-path query builder needs to plan and emit SQL.
UpdateModelInput
UpsertModelInput
Input shape for the upsert primitive — INSERT … ON CONFLICT (<pk>) DO UPDATE …. sql_values() must include the primary-key column (so the backend can target the conflict), and primary_key_value() exposes the PK separately so the runtime can issue a SELECT … FOR UPDATE before the upsert to drive Created vs. Updated event / audit semantics.
WriteSource
Anything a write-path query builder needs on top of ReadSource — create defaults, update / delete policy slots, audit + retention + versioning state, upsert column list, emitted event topics.

Functions§

authorize_procedure
canonical_request_string
Canonical string assembled by the envelope signing path: METHOD\nPATH\nQUERY\nCONTENT-TYPE\nbody-hex. Both seal and verify reconstruct the same string from the same inputs.
coalesce
Build a COALESCE(...) left-hand operand. The returned CoalesceExpr carries the column list; chain a comparator method (.lte, .eq, .is_null, …) to produce a FilterExpr the query builders can consume.
decode_codec_request
decode_transport_request_for
encode_codec_response
encode_codec_result
encode_codec_result_with_status
encode_transport_result
encode_transport_result_with_status
encode_transport_result_with_status_for
encode_transport_sequence_result
encode_transport_sequence_result_with_status
encode_transport_sequence_result_with_status_for
encode_transport_stream_result_with_status_for
Genuinely incremental counterpart to encode_transport_sequence_result_with_status_for for @stream procedures (cratestack#283): result carries the still-unconsumed item Stream rather than an already-collected Vec. Err here means a preflight failure (authorization, before anything was produced) — the ordinary buffered error path applies, since nothing has streamed to the client yet. A failure during the stream is a different thing entirely and never reaches this function as an Err: it’s absorbed into the item stream itself as the tag-48900 sentinel (see super::stream_sequence).
enrich_context_from_headers
Enrich a CoolContext with the request id (from traceparent) and the client IP (from Forwarded/X-Forwarded-For). Malformed traceparent headers are silently ignored here — the auth/header-validation layer is the right place to reject them, not the enrichment seam.
event_topic
find_duplicate_position
Detect duplicate keys in a batch input, loud-failing the whole request when found. Returns the first duplicate (by position) so the surfaced error can name a specific offending index. Linear- time, allocation-only in proportion to the input length.
is_orderable
Whether every hop is to-one. Ordering through a to-many hop is not expressible as a scalar correlated subquery, so generated asc()/ desc() accessors are gated on this (previously enforced by simply not emitting those methods past a to-many hop).
order_value_sql
Build the correlated-subquery expression that yields column at the end of hops, relative to the table reached by the first hop.
parse_client_ip
Extract the most-specific client IP available from the request headers, falling back to none. Prefers Forwarded (RFC 7239) over the legacy X-Forwarded-For. Banks running behind a single trusted L7 take the leftmost entry; deeper proxy chains must verify and rewrite at the edge.
parse_composite_id_attribute
Parses @@id([field1, field2, ...]) into its ordered list of local field names. Callers are responsible for checking that each name resolves to a real scalar field on the model.
parse_composite_unique_attribute
Parses @@unique([field1, field2, ...]) into its ordered list of local field names. Callers are responsible for checking that each name resolves to a real scalar field on the model.
parse_cuid
parse_emit_attribute
parse_filter_expression
parse_if_match_version
Parse an If-Match header carrying a strong ETag of the form "<int>". Returns None if the header is absent. Returns an error if the header is present but malformed (weak validators, non-integer payloads, etc.).
parse_index_attribute
Parses @@index([field1, field2, ...]), optionally followed by using: <method> and/or opclass: "<name>". Callers are responsible for checking that each field name resolves to a real scalar field on the model.
parse_query_pairs
parse_schema
parse_schema_file
parse_schema_named
parse_traceparent
Extract a W3C traceparent header, returning the trace-id portion when the header is present and well-formed. Returns Ok(None) when absent — callers should mint their own request id in that case so every audit row carries something. The trace-id is the second hyphen-delimited segment per W3C Trace Context; this implementation does not validate the flags/version segments since banks usually rebuild traceparent at the edge anyway.
point
Geographic point (WGS-84 lng/lat). The naming follows the PostGIS ST_MakePoint(x, y) convention — lng is the X axis (longitude), lat is the Y axis (latitude). Don’t accidentally swap them; the engine has no way to detect it and your filter will silently match points across the world.
resolve_order_target
Walk key (dot-separated, e.g. "author.profile.nickname") through catalog, following to-one relation edges one segment at a time and resolving the final segment against the current model’s scalar columns.
set_version_etag
Insert an ETag header onto a response, formatted as a strong validator over the integer optimistic-locking version.
validate_codec_request_headers
validate_codec_response_headers
validate_email
Pragmatic email check: requires exactly one @, non-empty local and domain parts, at least one . in the domain, and no whitespace. Not a full RFC 5322 grammar — that grammar admits forms (quoted local parts, IP literals) banks rarely accept anyway. Reject early; let real KYC flows do deeper validation.
validate_iso4217
ISO 4217 currency codes are 3 ASCII uppercase letters. We do not enforce the registered set here — that table churns and is downstream policy. Banks typically pin allowed currencies via a separate allow-list anyway.
validate_length
validate_range_decimal
Decimal-typed @range enforcement. The parser accepts integer bounds (@range(min: 0, max: 100)) on both Int and Decimal fields; the i64 bounds are promoted to Decimal here so monetary fields can declare the same shape as integer counters. Banks routinely write things like amount Decimal @range(min: 0) to forbid negative amounts at the framework layer — without this, the validator silently no-ops and out-of-range values reach the database.
validate_range_i64
validate_transport_request_headers
validate_transport_request_headers_for
validate_transport_response_headers
validate_transport_response_headers_for
validate_uri
wrap_filter
Fold a scalar FilterExpr outward through the traversed path, applying each hop’s quantifier. Mirrors what the macro previously emitted as nested FilterExpr::relation*(...) token trees.

Type Aliases§

CoolBody
Body bytes carried through the transport layer.
CoolEventFuture
Decimal