Core concepts

Concepts

The mental model in one page - contracts and layers, Resources, operations, results and the contract hash - with links to the detailed pages.

Read as Markdown

Aventara has four ideas: contracts and layers, Resources and operations, results and typing, and the contract hash.

Code
 schema.prisma + aventara.config.ts
              │  compile
              ▼
   core ─► application      client ─► GET /api/_contract ─► avclient generate ─► typed client
              (server only)  (the only layer served)

Contracts and layers

A contract is passive data: which Resources exist, which fields can be read, filtered, ordered or written, and which operations are available. It holds no code, so it can be serialized, hashed and versioned. Aventara compiles four from the same schema:

LayerUsed forServed over HTTP
CoreThe baseline everything else starts from.No
ApplicationYour trusted server-side code (framework.application.*).No
ClientRemote callers: the HTTP protocol and the generated frontend client.Yes, at GET <api>/_contract
AgentAI agents, through an MCP server (the agent layer).No: the MCP server builds its tools from it

The root of your configuration is the core layer; application and client are overlays on it that can hide more for their own callers, never less. What each layer exposes is set with exposed and exemptions (Exposure). A field hidden from the client layer is absent from the generated client's types. Details: Contract layers.

Resources and operations

A Resource is one Prisma model, keyed by its name (User, Post). Every Resource offers operations from five families, each with variants:

FamilyVariants
findfirst, unique, many, count
createone, many, count
updatefirst, unique, many, count
deletefirst, unique, count (no many with the Prisma 7 adapter)
upsertunique

Their meaning is fixed by the protocol; configuration can only switch them off, or run your own code around them (Pipelines). Each variant, with an example, is in Resources and operations.

Results and typing

Every operation answers one envelope, { data, code, cause }, on the wire. The generated client and your server-side calls (framework.application, framework.client, framework.transaction) resolve to data and throw a typed error for every failure; a first miss is null, a count is a number, and results are readonly. The type of a result follows your select exactly. Details: Results and typing.

Code
{ "data": { "id": 1, "email": "ada@example.com" }, "code": "A1002", "cause": null }

Branch on code, never on cause.message. The codes are listed in the HTTP protocol.

The contract hash

The client contract has a hash over everything it advertises, served as the ETag of /_contract and sent by the generated client on every request. If the server's contract has changed, the request is refused with A2005 (CONTRACT_MISMATCH) and the client throws AvContractMismatchError:

Code
Generated client contract does not match the server. Regenerate the client.

Details and the regenerate workflow: Contract hash.

Where to go next

To learnRead
What each layer seesContract layers
Hiding fields and operations per layerExposure
Every operation, with an exampleResources and operations
How results are typedResults and typing
Identity, ETag and stale clientsContract hash
Changing what each layer exposesConfiguration
The query languageQuerying

See also: Exposure, Exposing and hiding fields, Pipelines, Limits and safety.