Validate
Every declarative file in an app has a published JSON Schema. Wiring your editor to them is the cheapest quality gate available, and it catches most of what would otherwise fail a build.
https://schemas.revenexx.com/manifest.schema.json
https://schemas.revenexx.com/manifest.capabilities.schema.json
https://schemas.revenexx.com/schema.schema.json
https://schemas.revenexx.com/cockpit.schema.json
https://schemas.revenexx.com/settings.schema.json
https://schemas.revenexx.com/billing.schema.json
https://schemas.revenexx.com/search.schema.json
https://schemas.revenexx.com/analytics.schema.json
Point each file at its schema with $schema and your editor validates and completes as you type:
{
"$schema": "https://schemas.revenexx.com/manifest.schema.json",
"name": "serials"
}
additionalProperties is false at every level of the manifest, so a typo'd key fails rather than being silently ignored. That is the behaviour you want: warmups: true is a bug you find in your editor instead of wondering why the app is still cold.
Validate before you deploy
The loop after any change to a declaration:
revenexx apps capabilities --write # regenerate manifest.capabilities.json from schema.json
revenexx apps generate # regenerate the typed client
npm test # run the suite
Both generators are idempotent, so running them on an unchanged schema produces no diff — which makes a dirty working tree after them a useful signal that you forgot a step earlier.
In CI, run them and fail on a diff. An app whose generated files are out of date with its schema.json will deploy and then behave in ways the source does not explain.
What the schemas catch
- Missing required fields —
name,vendor,version,title,typein the manifest;entitiesin the schema;columnsand apkper entity. - Unknown keys, at every level.
- Wrong types and malformed enums.
- A
permissionsentry with more than one resource key, or a key that is not one of the nine. - An event name that is not exactly two dot-separated segments.
- A column type that is not one of the supported PostgreSQL types.
- A
tenant_idororg_idcolumn you tried to declare.
The rules that fail later
Some rules cannot be expressed in a single file's schema, because they are about how two files agree or about the platform-wide namespace. These pass locally and fail at apply or publish time.
Only at apply time
A dependencies or peerDependencies key that is not vendor/app. "markets": "^0.1" is a valid JSON object and an invalid dependency. See Dependencies.
A cross-app foreign key. A references naming another app's entity. See Relationships.
A notNull column with no default on a populated table, and a changed generated expression. See Migrations.
A dropped_columns tombstone the platform refuses — 422 while the column holds data or anything still references it.
Only at publish time
A summary longer than 255 characters. Put the prose in description; keep the summary to a line.
A tag naming rule. A tag must be a capability namespace this app defines or a dotted refinement of one, and a capability may only name a tag declared in the manifest's top-level tags. Because the capability register and the manifest are generated separately, a tag added to one and not the other passes every local check. See Tags.
An event-name shape. The two-segment rule is in the schema, but it is checked again here — so a hand-edited manifest that slipped past a stale editor config still fails on the way out.
A globally claimed name. A provides_scopes dimension, a provides_permissions key or a provides_roles subject another app already owns. There is nothing local that could know this: the namespace is platform-wide.
A pre-deploy checklist
- Every JSON file has its
$schemaand your editor reports no problems. dependenciesandpeerDependencieskeys all contain exactly one slash.- Every capability
summaryis one line, under 255 characters. - Every capability that names a
taghas that tag in the manifest'stags. - Every event name is exactly two lowercase dot-separated segments.
- Paged list capabilities declare
limit,offsetandorder; nothing else does. - Creates declare their
201; unique columns declare their409. revenexx apps capabilities --writeandrevenexx apps generateproduce no diff.npm testis green.versioninmanifest.jsonhas been bumped.
Next steps
- Manifest reference — the manifest's own validation notes.
- Testing — what the schemas cannot check.
- Deploying — the step after this one.
- Tags — the publish-time naming rules in full.