Contracts add optional field definitions and validation to entries. Entries can also contain JSON without a contract. Files do not use contracts. A contract belongs to the workspace and can be reused across buckets.
This feature is currently a local preview. It does not replace the published Entries or Files API.
Choose a contract
The entry drawer offers three explicit choices, for both new and migrated entries:
| Choice | Behavior |
|---|---|
| Automatic | Apply the first matching reference pattern in the entry's bucket. If nothing matches, no contract applies. |
| No contract | Skip automatic patterns and save without contract validation. |
| A contract name | Use that contract, overriding bucket patterns. |
The drawer shows the matched pattern when Automatic applies. A manual choice stays selected when the entry is edited or its reference changes. Changing the selection does not remove existing JSON fields or translations.
Names such as pages.v1 are literal names chosen by the user. Contracts have no built-in versions.
Order reference patterns
Open Objects → Contracts → Reference patterns, choose a bucket, and use the up/down buttons to arrange its patterns. This is one order across all contracts in that bucket. Save to apply it.
Patterns are checked from top to bottom. The first match wins; an exact match does not automatically outrank a broader pattern. Put exceptions above general patterns. A manual entry contract or No contract always takes precedence.
| Pattern | Matches |
|---|---|
pages/home |
That exact reference |
pages/* |
One reference segment after pages/ |
pages/** |
Nested references under pages/ |
pages/blog-* |
References starting with pages/blog- |
Patterns use wildcards, not regular expressions. References need no .json extension. New patterns added from a contract editor are appended to the bucket's order. Contract rules remain inside the contract editor.
Save contract changes
Changing validation rules, validation mode, or reference patterns asks you to confirm before saving. Choose Keep editing to return to the draft, or Save changes to save and start checking affected entries. Presentation-only edits such as field labels do not need this confirmation.
Saving closes the drawer immediately. A background job checks existing entries, including translations and relationships, and stores the results used by the overview's red indicators. Previous indicators stay visible while checks run. Corrected entries lose their indicators once checked. Entry content, publication status, authors, timestamps and edit versions are unchanged.
Opening an entry checks its current data immediately and shows the details. New entries and API writes continue to validate synchronously against current rules; they do not wait for background checks. Existing API endpoints and payloads remain unchanged.
Reference patterns retain their visible order and first-match behavior. Changing, removing or reordering patterns checks entries in the previous and new buckets, plus manual users of the changed contract and entries with relationship constraints. No contract selections remain explicit opt-outs.
Checks run on the application's validation queue in batches of up to 100 entries. Run a local queue worker (php artisan queue:work --queue=validation --sleep=1 --tries=3) when testing this flow. Jobs retry failures; failed checks keep their previous results and the overview explains that an entry can be opened to check again. Internal request tokens skip superseded checks; these are not contract versions.
Field labels in the editor
The field type picker uses Text, Number, Yes/no, Group, List, Related entry, File, Date and JSON where supported. These are display labels: stored types such as string, boolean and relation are unchanged. Groups and complex lists still use inline JSON inputs in entry drawers.
Entry metadata uses Publication status for Draft/Published, separate from any user-defined field named Status.
Validation and relationships
Enforce blocks writes with errors; warning rules do not block. Warn reports problems while allowing the write. Off skips validation. Changing a contract or pattern can make saved entries invalid: their overview indicator reflects the latest completed check, while opening the drawer checks current data. Existing data is not automatically rewritten or deleted.
Relationship rules can constrain the target bucket and contract and allow one or multiple entries. Relationships continue to use stable entry IDs; reference names are for navigation. Removing a target entry's contract may make a contract-constrained relationship invalid.
Existing API clients
Keep using the same API endpoints, bucket/type names, entry IDs, field payloads, locales, and authentication. Existing v1/v2 response shapes and file upload/download flows remain available. Clients do not have to adopt object references or send a contract selection to keep using migrated entries.
The migration retains original content-type definitions and compatibility rows for existing queries, relationships, attachments, and translations. Contract changes can intentionally change which data passes validation; that is a content-model change, not a new request format.
Entries created through Objects in a migrated collection remain visible through that collection's existing API. Viresso recognizes the collection from the first part of the reference, or from its converted contract within the same bucket. A contract from another bucket does not change collection membership. New objects outside migrated collections use the Objects API.
For the optional Objects API, contract is additive:
- On creation, omitted or
nullmeans Automatic. - On update, omitted preserves the current choice;
nullreturns to Automatic. falseexplicitly selects No contract.- A string selects the named workspace contract.
{
"ref": "products/inflatable-pillow",
"contract": "product.v3",
"data": {
"name": "Inflatable pillow",
"price": 24.95
}
}
The Objects API uses POST /api/v1/{workspace}/objects and PATCH /api/v1/{workspace}/objects/{objectId}. Updates include the full ref, JSON data, and current lock_version. These routes require an activated workspace. Production activation is off by default and requires the global Objects setting plus explicit workspace activation after conversion checks. They are not part of the published OpenAPI specification. Disabling the new interface does not stop compatibility writes to converted entries. Existing clients should continue using the documented Entries and Files endpoints.