CrateStack Package Selection and Dependency Decision Log
Status
Accepted for the initial workspace bootstrap. Some crates remain intentionally deferred until after the parser, macro, and codec spine is stable.Date
2026-04-26Scope
This document records the current package and dependency decisions for CrateStack v0. It covers:- runtime dependencies
- procedural macro dependencies
- parser and diagnostics dependencies
- database dependencies
- HTTP framework dependencies
- codec dependencies
- COSE dependencies
- generated-client dependencies
- testing dependencies
- dependencies explicitly deferred or rejected
Cargo.lock and release policy. This document records architectural dependency choices and the rationale behind them.
1. Dependency Philosophy
CrateStack should be dependency-conscious but not dependency-minimal at the cost of correctness or developer experience. Dependency choices should optimize for:- correctness
- long-term maintainability
- Rust ecosystem maturity
- compile-time ergonomics
- security posture
- clear ownership boundaries
- compatibility with Axum, Tokio, SQLx, Serde, CBOR, and COSE
- avoiding JSON as a core assumption
- keeping optional features optional
2. Feature and Crate Boundary Policy
Dependencies should live in the narrowest crate that needs them. Recommended workspace:cratestack-coremust not depend on Axum.cratestack-coremust not depend on SQLx unless unavoidable.cratestack-coremust not depend on JSON-specific crates.cratestack-coremay depend on Serde traits.cratestack-sqlxowns SQLx.cratestack-axumowns Axum, Tower, HTTP-body integration.cratestack-codec-cborowns the Serde-based CBOR codec surface built onminicbor-serde.- JSON support currently lives inline in
cratestack-client-rustrather than a dedicatedcratestack-codec-jsoncrate. - COSE is currently a reserved runtime seam rather than a dedicated implemented
cratestack-cosecrate. application/cbor-seqis a planned framing-aware transport mode and is not implemented today.cratestack-macrosowns proc-macro dependencies.cratestack-client-rustowns generated Rust client runtime support.cratestack-client-dartowns generated Dart or Flutter package generation.cratestack-cliowns CLI and terminal diagnostics dependencies.cratestack-lspowns LSP/editor protocol behavior over parser and semantic surfaces.cratestack-vscodeis a thin editor wrapper that contributes the.cstacklanguage and launchescratestack-lsp.
2.1 Current Direction Update
Bootstrap implementation started with generated server-side CRUD and procedure routes. The current target direction is broader:- generated HTTP routes are canonical APIs
- Rust client generation is a first-class output
- Dart client generation currently targets a generated byte-oriented bridge/runtime abstraction plus Riverpod wiring rather than owning Dio directly, uses bridge JSON bytes as an internal interop format while keeping transport codec ownership in Rust, renders through repo-managed MiniJinja templates that callers can override with a template directory, emits multiple sibling files per client package, and now exposes canonical
fields/include/includeFields[path]query params plus generated field/include constants, generated selection builders, and projected wrapper objects even though exact selection-aware typed responses are still incomplete; the Rust side now also exposes nested selection builders, a generated schema-native client facade, additive selectedget/listhelpers, and request-authorizer hooks over the canonical HTTP contract - JSON and CBOR are first-class codecs, while COSE remains an envelope layer
- transport architecture is split into codec, framing, and envelope; sequence transports such as
application/cbor-seqbelong to framing - CRUD exposure, field visibility, and field filterability are schema-controlled concerns
- custom fields resolve through generated resolver traits
- authentication remains delegated to host integrations
3. Dependency Categories
Each dependency decision uses one of these statuses:4. Core Runtime Dependencies
4.1 serde
Status: ADOPT
Purpose:
- derive serialization/deserialization for generated models
- enable codec-agnostic request/response handling
- support CBOR, JSON, and future codecs
cratestack-core- generated schema code
- codec crates
- REST integration crates
4.2 thiserror
Status: ADOPT
Purpose:
- define typed library errors
- derive
std::error::Error - keep error types structured and stable
cratestack-core- parser
- policy engine
- SQLx integration
- codec crates
- COSE crate
thiserror is better than anyhow for public error types because it preserves structured error variants.
Decision:
Use thiserror for public and internal library errors.
4.3 anyhow
Status: ADOPT OPTIONAL
Purpose:
- application examples
- CLI command plumbing
- integration tests
cratestack-cli- examples
- tests
anyhow is convenient for binaries and examples, but should not be used as the main public error surface of CrateStack library crates.
Decision:
Use in CLI/examples/tests only. Do not expose as the primary library error type.
4.4 bytes
Status: ADOPT
Purpose:
- efficient HTTP body byte handling
- request/response body integration
- codec/envelope pipeline
cratestack-corecratestack-axum- codec crates
- envelope crates
bytes is standard across the Tokio/Hyper/Axum ecosystem.
Decision:
Adopt for byte-oriented transport internals.
4.5 http
Status: ADOPT
Purpose:
- HTTP status codes
- headers
- content type handling
- framework-neutral HTTP types where possible
cratestack-core, if framework-neutral HTTP concepts are neededcratestack-axum
http crate avoids coupling basic status/header concepts directly to Axum.
Decision:
Adopt where framework-neutral HTTP types are useful.
4.6 tracing
Status: ADOPT OPTIONAL
Purpose:
- structured logs
- request tracing
- generated query/procedure diagnostics
- policy decision traces in debug mode
cratestack-sqlxcratestack-axum- optionally core internals
tracing is the standard async Rust instrumentation ecosystem.
Decision:
Use internally where helpful, but avoid forcing a logging setup on applications.
5. Async Runtime Dependencies
5.1 tokio
Status: ADOPT
Purpose:
- async runtime compatibility
- required by Axum/SQLx setup
- examples and integration tests
cratestack-axumcratestack-sqlx- examples
- integration tests
5.2 async-trait
Status: ADOPT
Purpose:
- generated async procedure traits
- integration traits where async trait methods are needed
- generated schema code
cratestack-coreorcratestack-axum
async-trait, especially for generated procedure handler traits stored behind trait objects.
Decision:
Use async-trait in v0 for procedure implementations and handler registration ergonomics.
Review later when native async trait ergonomics and object-safety patterns are sufficient.
6. Database Dependencies
6.1 sqlx
Status: ADOPT
Purpose:
- async PostgreSQL access
- connection pooling
- query execution
- row decoding
- transactions
cratestack-sqlx- generated schema code where needed
macrosis useful for tests, examples, and static queries, but generated dynamic queries should primarily useQueryBuilder.jsonhere refers to database JSON/JSONB support, not HTTP JSON transport.- exact feature set should be audited before publishing v0.
QueryBuilder a good match.
Decision:
Use SQLx as the v0 database backend.
6.2 sea-query
Status: DEFER
Purpose considered:
- SQL AST construction
- database-agnostic SQL generation
QueryBuilder is sufficient for v0 dynamic SQL generation. Adding SeaQuery now would add another abstraction layer before the SQL model is stable.
Decision:
Do not use SeaQuery in v0. Reconsider when multi-database support is planned.
6.3 diesel
Status: REJECT FOR v0
Purpose considered:
- compile-time query safety
- mature ORM-like Rust database access
6.4 sea-orm
Status: REJECT FOR v0
Purpose considered:
- higher-level ORM over SeaQuery
- entity model generation
7. HTTP and REST Dependencies
7.1 axum
Status: ADOPT
Purpose:
- v0 HTTP framework
- generated REST routes
- extractors
- request extensions
- response conversion
cratestack-axum- generated route code
- examples
json unless cratestack-codec-json or examples specifically require it.
Rationale:
Axum is ergonomic, Tokio-native, Tower-based, and has a strong extractor model. It is a good fit for generated REST routes.
Decision:
Adopt Axum as the only supported HTTP framework in v0.
7.2 tower
Status: ADOPT OPTIONAL
Purpose:
- middleware compatibility
- service abstractions
- potential auth/context extraction layer
cratestack-axum
cratestack-axum, but avoid exposing unnecessary Tower complexity in the public API.
7.3 tower-http
Status: DEFER
Purpose considered:
- tracing middleware
- compression
- CORS
- request ID middleware
tower-http, but generated routes should not require it.
Decision:
Do not require tower-http in v0 library crates. Use only in examples if helpful.
8. Parser and Diagnostics Dependencies
8.1 chumsky
Status: ADOPT
Purpose:
.cstackschema parser- parser combinators
- source spans
- recoverable parse errors
cratestack-parser
- isolate parser grammar in
cratestack-parser - keep parser modules small
- maintain extensive parser tests
- snapshot parser errors
8.2 ariadne
Status: ADOPT
Purpose:
- compiler-style diagnostic rendering
- source span labels
- CLI and macro diagnostics support
cratestack-parsercratestack-cli- possibly
cratestack-macros
.cstack needs clear schema diagnostics. Ariadne produces readable source-highlighted error reports.
Decision:
Use Ariadne for human-readable diagnostics.
8.3 miette
Status: WATCH / DEFER
Purpose considered:
- structured diagnostics
- pretty terminal reports
- source spans
- CLI error handling
cratestack-cli if Ariadne alone is not sufficient.
8.4 pest
Status: REJECT FOR v0
Purpose considered:
- grammar-driven parser
8.5 winnow
Status: WATCH
Purpose considered:
- high-performance parser combinators
9. Procedural Macro and Code Generation Dependencies
9.1 proc-macro2
Status: ADOPT
Purpose:
- stable token stream manipulation outside compiler proc-macro API
cratestack-macroscratestack-codegenif separated
9.2 quote
Status: ADOPT
Purpose:
- generate Rust token streams
cratestack-macroscratestack-codegen
9.3 syn
Status: ADOPT
Purpose:
- parse macro input
- parse literal schema path
- possible future macro options
cratestack-macros
include_schema! initially only needs a string literal, but future macro configuration may need more parsing. syn is the standard proc-macro parsing library.
Decision:
Adopt for macro input parsing.
9.4 prettyplease
Status: ADOPT OPTIONAL
Purpose:
- format generated code for debug output
- potential
cratestack print-codeCLI command
cratestack-cli- codegen debug tooling
10. Codec Dependencies
10.1 minicbor-serde
Status: ADOPT
Purpose:
- CBOR encoding and decoding through Serde
- first-class CrateStack codec implementation
cratestack-codec-cbor- possibly
cratestack-coseindirectly
minicbor-serde provides Serde-compatible CBOR serialization/deserialization on top of minicbor and aligns with the planned generic CoolCodec trait while keeping the door open to lower-level minicbor control where needed.
Decision:
Use minicbor-serde for the official CBOR codec.
10.2 serde_json
Status: ADOPT OPTIONAL
Purpose:
- optional JSON codec
- examples if needed
- debugging utilities
cratestack-codec-json- tests/examples only
10.3 serde_cbor
Status: REJECT FOR v0
Purpose considered:
- CBOR encoding/decoding through Serde
minicbor-serde is preferred for the official CBOR codec.
Decision:
Do not use serde_cbor in v0.
10.4 minicbor
Status: ADOPT SUPPORTING
Purpose considered:
- CBOR encoding/decoding
- lower-level CBOR control
minicbor-serde for Serde-based CBOR transport and keeps minicbor available as the underlying low-level codec when sequence-aware or lower-level CBOR handling is needed.
Decision:
Do not use in v0 official codec. Reconsider for advanced codec crates later.
11. COSE and Cryptography Dependencies
11.1 coset
Status: ADOPT OPTIONAL
Purpose:
- COSE structure handling
- CoseSign1 support
- CBOR Object Signing and Encryption data model
cratestack-cose
cratestack-cose.
11.2 Signature Algorithm Crates
Status: DEFER / ADOPT OPTIONAL PER ALGORITHM Purpose:- implement actual signing and verification for selected COSE algorithms
cratestack-cose. Add concrete algorithm adapters only when required by a target deployment.
Recommended initial algorithm if one must be selected:
- compact signatures
- common modern choice
- simpler operational profile than ECDSA in many contexts
11.3 cose-rust
Status: WATCH / REJECT FOR INITIAL v0
Purpose considered:
- higher-level COSE message encode/decode support
cose-rust may provide useful examples and message support, but coset is the preferred initial choice because it is strongly aligned with Ciborium and provides structured COSE types.
Decision:
Do not use as the initial COSE dependency. Reconsider if coset proves insufficient.
11.4 secrecy
Status: ADOPT OPTIONAL
Purpose:
- protect secret key material in memory APIs
- avoid accidental debug logging of secrets
cratestack-cose- application examples involving keys
11.5 zeroize
Status: ADOPT OPTIONAL
Purpose:
- zero memory for secret material
cratestack-cose
12. Date, Time, ID, and Value Dependencies
12.1 uuid
Status: ADOPT
Purpose:
- support
Uuidschema scalar - database UUID fields
- transport serialization
- generated schema code
cratestack-corecratestack-sqlx
Uuid scalar.
12.2 chrono
Status: ADOPT WITH CAUTION
Purpose:
- support DateTime values
- SQLx integration
- generated schema code
cratestack-sqlx
DateTime, unless the team decides to standardize on time before implementation.
12.3 time
Status: WATCH / POSSIBLE SUBSTITUTE FOR CHRONO
Purpose considered:
- modern date/time types
- SQLx integration
time crate is a strong modern alternative to Chrono.
Decision:
Do not support both chrono and time in generated public model types in v0. Pick one before implementation. Default recommendation: use Chrono for ecosystem compatibility unless the team strongly prefers time.
12.4 indexmap
Status: ADOPT OPTIONAL
Purpose:
- preserve schema declaration order
- deterministic codegen
- stable diagnostics
cratestack-core- parser/analyzer
- codegen
IndexMap is useful for preserving insertion order while enabling lookup.
Decision:
Use if the IR benefits from ordered maps. Otherwise use vectors plus explicit lookup maps.
13. CLI Dependencies
13.1 clap
Status: ADOPT
Purpose:
cratestack checkcratestack print-ir- future commands
cratestack-cli
13.2 camino
Status: ADOPT OPTIONAL
Purpose:
- UTF-8 path handling in CLI and macro helpers
cratestack-cli- possibly parser diagnostics
std::path.
14. Testing Dependencies
14.1 insta
Status: ADOPT
Purpose:
- snapshot parser diagnostics
- snapshot generated SQL
- snapshot generated Rust debug output
- snapshot IR
- parser tests
- policy tests
- codegen tests
14.2 pretty_assertions
Status: ADOPT OPTIONAL
Purpose:
- readable diff output in tests
- unit tests
14.3 testcontainers
Status: ADOPT OPTIONAL
Purpose:
- PostgreSQL integration tests
- full SQLx/REST tests
- integration tests
DATABASE_URL-driven test mode.
14.4 reqwest
Status: ADOPT OPTIONAL
Purpose:
- end-to-end HTTP tests
- Rust generated-client runtime for CrateStack service-to-service calls
- integration tests
cratestack-client-rust, which backs generated Rust clients emitted byinclude_schema!and client-only generated clients emitted byinclude_client_macro!
cratestack-client-rust and in black-box HTTP integration tests. Prefer the generated client facade over handwritten reqwest calls when the target service exposes a CrateStack .cstack schema.
15. Development Tooling Dependencies
15.1 rustfmt
Status: ADOPT VIA TOOLCHAIN
Purpose:
- format source code
- format generated code snapshots where applicable
15.2 clippy
Status: ADOPT VIA TOOLCHAIN
Purpose:
- lint library and generated code where possible
15.3 cargo-deny
Status: ADOPT
Purpose:
- license checks
- advisory checks
- duplicate dependency detection
- banned dependency enforcement
cargo-deny before first public release.
15.4 cargo-audit
Status: ADOPT OPTIONAL
Purpose:
- RustSec advisory checks
cargo-audit directly or through cargo-deny. Avoid duplicate CI noise if cargo-deny covers advisories.
16. Dependency Feature Matrix
16.1 cratestack-core
Required:
cratestack-sqlx, not cratestack-core.
16.2 cratestack-parser
Required:
16.3 cratestack-macros
Required:
16.4 cratestack-sqlx
Required:
16.5 cratestack-axum
Required:
16.6 cratestack-codec-cbor
Required:
16.7 cratestack-codec-json
Required:
16.8 cratestack-cose
Required:
16.9 cratestack-cli
Required:
17. Initial Cargo Feature Strategy
17.1 Root cratestack Features
Recommended root features:
default = [] to prevent accidental JSON assumptions and keep dependency boundaries honest.
Before public release, decide whether defaults should optimize for general adoption or strict minimalism.
Implementation note:
The workspace bootstrap in this repo adopts default = [].
18. Rejected Dependencies Summary
18.1 Rejected for v0
18.2 Deferred
18.3 Watch List
19. Security Review Notes
Dependencies requiring special security attention:- Run
cargo-denyin CI. - Run RustSec advisory checks.
- Review cryptography dependencies before enabling COSE signing/encryption in production.
- Keep COSE key handling behind traits.
- Avoid storing secret key material in long-lived CrateStack structs unless necessary.
- Use
secrecyandzeroizeif private key bytes are handled. - Snapshot-test policy SQL generation.
- Ensure all SQL uses bind parameters.
- Keep JSON optional and out of core.
- Validate unsupported content types explicitly.
20. Licensing Policy
Before first public release:- Configure
cargo-denylicense policy. - Allow permissive licenses such as MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, and Unicode-3.0 if needed.
- Review crypto crate licenses manually.
- Review transitive dependencies for GPL/AGPL/LGPL restrictions.
- Add a dependency approval step for new public dependencies.
21. Version Pinning Policy
For library crates:- use semver-compatible version ranges in
Cargo.toml - do not pin exact patch versions unless necessary
- use
Cargo.lockfor reproducible workspace builds
- use compatible major/minor versions
- regenerate lockfiles regularly
- update promptly on advisories
- document any temporary pins
22. Dependency Review Checklist
Every new dependency must answer:- Which crate owns this dependency?
- Is this dependency required or optional?
- Does it belong in core?
- Does it pull JSON into core?
- Does it pull Axum into core?
- Does it pull SQLx into core?
- Does it affect public generated types?
- Does it affect MSRV?
- Does it introduce unsafe code?
- Does it introduce cryptography?
- Does it introduce native dependencies?
- What is the license?
- Is it actively maintained?
- Are there viable alternatives?
- How will it be tested?
23. Recommended Initial Dependency Set
For the first implementation sprint, start with only:24. Final Dependency Decisions
For CrateStack v0, the team should proceed with these major decisions:- Use SQLx for database execution.
- Use Axum for REST integration.
- Use Tokio as the async runtime.
- Use Chumsky for
.cstackparsing. - Use Ariadne for schema diagnostics.
- Use Serde as the generated type serialization contract.
- Use
minicbor-serdeas the official Serde-based CBOR codec surface, withminicboravailable for lower-level control. - Use Coset for optional COSE support.
- Use
thiserrorfor library errors. - Use
anyhowonly in CLI/examples/tests. - Use
quote,syn, andproc-macro2for macro codegen. - Keep JSON optional and outside core.
- Keep COSE optional and outside core.
- Defer SeaQuery until multi-database support is designed.
- Reject Diesel and SeaORM for v0.
24.1 Implementation Kickoff Decisions
The first repo implementation slice makes these choices explicit:chronois the initialDateTimetype.- The implemented crates are
cratestack,cratestack-core,cratestack-parser,cratestack-policy,cratestack-macros,cratestack-codec-cbor,cratestack-codec-json,cratestack-axum,cratestack-cli, andcratestack-sqlx. cratestack-axumandcratestack-codec-jsonare implemented, whilecratestack-coseremains deferred.cratestack-cliprints the parsed IR with Rust debug formatting rather than a JSON renderer to keep JSON out of the initial dependency surface.- The current SQLx slice supports generated delegate scaffolding for
create,find_many,find_unique,update, anddelete, along with generated create/update input structs. - Generated SQL currently maps schema model and field names to snake_case SQL identifiers and uses naive pluralized snake_case table names.
find_manycurrently supports a minimal query IR: AND-combinedeq,ne,in, stringcontains, stringstarts_with, boolean convenience filters, null-aware optional-field filters, explicit ordering, limit, and offset.- Generated field reference modules expose schema-specific helpers such as
cratestack_schema::post::published()for the current filter/order API. - Generated create inputs currently omit
@idand@default(...)fields, and generated update inputs emit only changed columns. - Read-policy support now exists for
@@allow(...)and@@deny(...)rules onfind_many/find_unique, with deny taking precedence over allow. - Canonical policy literals, predicates, relation quantifiers, and procedure-policy evaluation now live in
cratestack-policy, which is shared by macro lowering and runtime enforcement. - The supported model-policy subset now includes list/detail read splits, recursive to-one traversal, dotted to-many quantifiers (
some/every/none), nested auth paths, and create-time relation checks when the root join columns are available from create input or auth-derived defaults. - Create, update, and delete policy enforcement now exists for the same canonical policy surface; create checks run against generated input values plus auth context after applying
@default(auth().field)defaults, and create-time relation checks can trigger DB lookups when the required join columns are known. - DB-backed integration coverage for policy enforcement now exists behind an env-gated test path using
CRATESTACK_TEST_DATABASE_URL, andcratestack/compose.ymlnow provides a local PostgreSQL 18 target for that loop. - Procedure policy execution now exists through generated wrappers under
cratestack_schema::procedures::*, supports grouped expressions plus nestedargs.<field>comparisons, and can delegate DB-backed row auth through@authorize(Model, action, args.path). - Built-in
Page<T>procedure returns now exist for declared model/type items, lower to a canonicalitems/totalCount/pageInfoenvelope, and decode through the generated Rust and Dart client surfaces without introducing general schema generics. - Models can now opt into paged generated list responses with bare
@@paged; that changes the generated top-level list route plus Rust/Dartlist(...)and projection-drivenlistView(...)helpers to usePage<Model>/Page<ProjectedModel>while keeping non-paged models on plain array responses. CoolContextnow carries a structured principal surface withactor,session,tenant, and free-form claims while preserving legacyauth().fieldcompatibility and exact-key-first lookup behavior.- Generated procedure registry traits now exist and currently use
Sendfutures rather than a larger plugin/runtime abstraction. - Model-level
@@emit(created|updated|deleted)directives now exist for the current narrow eventing slice; generated schema modules expose typed subscription helpers undercratestack_schema::events, generated SQLxcreate/update/deletepaths now write matching envelopes into a transactional PostgreSQL outbox, and the generated event surface exposes an explicit drain hook for in-process delivery attempts. - A new
cratestack-axumcrate now provides minimal codec/body response helpers, and generated schema modules now exposemodel_router,procedure_router, and combinedrouterhelpers. - Generated Axum model routes now cover
GET,POST,PATCH, andDELETEfor generated model endpoints, with canonicalfields, nested declared-relationincludepaths, canonicalsort,limit,offset, scalar equality filters, and a small route-layer operator suffix set (__ne,__lt,__lte,__gt,__gte,__in,__contains,__startsWith,__isNull) on list routes, includingcuid, UUID, and RFC3339 DateTime parsing. LegacyorderByremains accepted as a compatibility alias forsort. - Generated list routes now accept canonical grouped
where=expressions and can compile recursive relation filters such asauthor.email=owner@example.comoruser.sessions.some.label__startsWith=Primarywhen the schema declares explicit@relation(fields:[...],references:[...])metadata. - The current grouped route grammar is contract-stable as
whereExpr := orExpr,orExpr := andExpr ("|" andExpr)*,andExpr := factor ("," factor)*, andfactor := predicate | "(" whereExpr ")" | "not(" whereExpr ")". That meansnot(...)binds tighter than,,,binds tighter than|, and repeated,/|chains are left-associative unless parentheses override them. Legacyor=is still accepted only as a compatibility shortcut for a top-level OR list; canonical docs and new callers should prefer groupedwhere=because it is the only route form that supports nesting and unary negation. - To-many relation filters now require explicit quantifiers (
some,every,none) instead of the earlier generic nested-path shape, relation metadata validation now rejects mismatched scalar types betweenfields:[...]andreferences:[...], and the same relation/query surface has typed DSL parity through generated compatibility helpers and builder-styleFilterExprcomposition. - Generated list routes now support nested to-one relation-aware ordering such as
sort=author.emailorsort=author.profile.nicknamethrough recursive correlated subqueries, and the generated model descriptor metadata now exposes per-resource allowedfields,include, andsortselections for route validation. Generated typed field modules still expose matching delegate helpers in both compatibility-function and builder-style forms. Delegate callers can use compatibility helpers such aspost::author::email_desc()or builder paths such aspost::author().email().desc()andpost::author().profile().nickname().eq(...). Generated typed field modules also expose quantified to-many filter paths such asuser::sessions().some().label().contains(...), while cycle-aware code generation stops repeating relation expansions likeuser.sessions.some.user.sessions....FilterExprnow supports chainable.and(...)and.or(...)composition so the typed builder DSL can express grouped boolean filters without manually callingFilterExpr::all(...)orFilterExpr::any(...). Missing related rows sort with explicitNULLS LASTbehavior and the model primary key is auto-appended as a tie-break when the caller does not already specify it; any path that crosses a to-many relation remains intentionally unsupported for ordering, shallowincludeonly materializes directly declared relations, and the generated Dart client now exposes canonicalfieldsandincludequery options plus per-model field/include constant groups even though selection-aware response typing is still incomplete. - The generated HTTP layer now enforces a single configured codec through
AcceptandContent-Typeheader checks and uses dedicated406/415error variants rather than treating those mismatches as generic bad requests. - A new
cratestack-client-rustspike now exercises CBOR-first client calls against generated Axum-compatible routes, exposes an FFI-ready safe-Rust runtime bridge, and persists a narrow request journal through an abstract state store with in-memory and JSON-file implementations. cratestack-client-store-sqliteandcratestack-client-store-redisnow provide opt-in durable request-journal and state-version store implementations for the client runtime.- A new
cratestack-client-fluttercrate now wraps the runtime bridge with byte-oriented safe-Rust APIs for Dart and Flutter callers without introducing raw pointer code into this workspace, but it does not yet expose persisted state or runtime-configurable SQLite selection through its public surface. cratestack-client-dartnow renders from repo-managed templates under its owntemplates/directory, the CLI can accept a template override directory so projects can customize emitted Dart without forking the generator crate, the generated Dart seam no longer exposesCrateStackWireCodec, and the emitted output is now a richer Flutter-style package scaffold rather than a single flat file.- The runtime bridge now treats bridge JSON bytes as an internal interop format while exposing runtime-wide transport config for
cborandjson; COSE remains a reserved future envelope seam, and the generated Dart package still does not expose a typed remote-error surface. - The project-local client runtime architecture is documented in
../architecture/client-runtime.md; a raw exported ABI wrapper, signing integration, a fully typed Rust-owned Dart bridge, persisted-state exposure, runtime-configurable SQLite selection, and eventual removal of the bridge JSON transcode remain follow-up work. - The current model HTTP surface still forwards directly into generated SQLx delegates and only exposes a narrow route-layer query subset rather than the full delegate filter DSL.
- Richer policy parsing, broker/webhook fan-out, stronger event-delivery guarantees beyond the current transactional outbox plus in-process drain loop, and broader procedure runtime features are still deferred.
cargo-denyconfiguration is checked in atcratestack/deny.tomlas part of the release-oriented workspace bootstrap.- Generated telemetry now uses direct
tracingspans/events for procedure authorization and invocation, generated procedure routes, and generated model list routes, while subscriber setup, filtering, and any exporter integration remain host-owned concerns.
25. Open Dependency Questions
- Should CrateStack standardize on
chronoortimeforDateTime? - Should the root crate have default features or require explicit opt-in?
- Should
sqlxmacros be enabled in generated user dependencies or only in tests/examples? - Should COSE v0 include a concrete Ed25519 implementation or only signer/verifier traits?
- Should JSON codec be shipped in v0 or delayed until after CBOR is stable?
- Should
miettereplace or supplement Ariadne in CLI diagnostics? - Should generated code depend directly on SQLx derive macros, or should row decoding be centralized in
cratestack-sqlx? - Should
towerbe exposed in public APIs or kept internal tocratestack-axum?
26. Immediate Action Items
- Create workspace crate skeleton.
- Add minimal dependency sets per crate.
- Configure
cargo-deny. - Configure CI for fmt, clippy, tests, and deny.
- Implement parser spike with Chumsky.
- Implement diagnostics spike with Ariadne.
- Implement
CoolCodecon top of theminicbor-serde/minicborCBOR stack. - Implement macro spike with
include_schema!reading a schema file. - Implement SQLx query spike using
QueryBuilder<Postgres>. - Implement Axum binary-body route spike without enabling Axum JSON.
- Defer COSE until the codec and envelope boundaries are proven.