{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "OrdinaryHostConfig",
"description": "Config definition for an Ordinary API Instance",
"type": "object",
"properties": {
"domain": {
"type": "string"
},
"contacts": {
"type": "array",
"items": {
"type": "string"
}
},
"public_dns_ip": {
"type": [
"array",
"null"
],
"items": {
"type": "integer",
"format": "uint8",
"minimum": 0,
"maximum": 255
},
"minItems": 4,
"maxItems": 4
},
"env_name": {
"type": "string",
"default": "development"
},
"limits": {
"$ref": "#/$defs/OrdinaryHostLimits",
"default": {
"app_domains": [],
"privileged_domains": [],
"proxy": {
"count": 255,
"disallowed_targets": []
},
"middleware": {
"count": 65535,
"disallowed_endpoints": []
},
"function": {
"count": 255,
"max_timeout": 10
},
"auth": {},
"monitor": {},
"storage": {
"max_storage": 20000000000,
"max_app_storage": 50000000,
"assets": {
"allowed_extensions": [
"otf",
"ttf",
"woff",
"woff2",
"txt",
"xml",
"html",
"css",
"css.map",
"csv",
"js",
"png",
"apng",
"gif",
"svg",
"jpg",
"jpeg",
"bmp",
"tif",
"tiff",
"webp",
"avif",
"ico",
"pdf",
"json",
"wasm"
],
"max_store_size": 100000000,
"max_asset_size": 1500000
},
"artifact": {
"max_store_size": 25000000,
"max_artifact_size": 15000000
},
"cache": {
"max_size_range": [
1000000,
10000000
],
"max_count_range": [
100,
500
]
},
"database": {
"max_model_definitions": 255,
"max_model_fields": 255,
"max_item_size": 400000,
"max_field_size": 100000
},
"secrets": {
"max_count": 225,
"max_size": 2000
}
}
}
},
"proxied_metrics": {
"type": "array",
"items": {
"$ref": "#/$defs/ProxiedMetric"
},
"default": []
},
"console": {
"description": "whether to serve the web console",
"type": "boolean",
"default": false
},
"invite_token_link": {
"description": "link to the location where you are able to obtain an invite token",
"type": "string",
"default": "/"
},
"extensions": {
"description": "configuration for extensions",
"type": "array",
"items": {
"$ref": "#/$defs/OrdinaryHostExtensionConfig"
},
"default": []
}
},
"required": [
"domain",
"contacts"
],
"$defs": {
"OrdinaryHostLimits": {
"type": "object",
"properties": {
"app_domains": {
"type": "array",
"items": {
"type": "string"
}
},
"privileged_domains": {
"type": "array",
"items": {
"type": "string"
}
},
"proxy": {
"$ref": "#/$defs/ProxyLimits"
},
"middleware": {
"$ref": "#/$defs/MiddlewareLimits"
},
"function": {
"$ref": "#/$defs/FunctionLimits"
},
"auth": {
"$ref": "#/$defs/AuthLimits"
},
"monitor": {
"$ref": "#/$defs/MonitorLimits"
},
"storage": {
"$ref": "#/$defs/StorageLimits"
}
},
"required": [
"app_domains",
"privileged_domains",
"proxy",
"middleware",
"function",
"auth",
"monitor",
"storage"
]
},
"ProxyLimits": {
"type": "object",
"properties": {
"count": {
"description": "max number of proxies per application.",
"type": "integer",
"format": "uint8",
"minimum": 0,
"maximum": 255
},
"disallowed_targets": {
"description": "a list of any internal or external target\nregexes that should be disallowed.",
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"count",
"disallowed_targets"
]
},
"MiddlewareLimits": {
"type": "object",
"properties": {
"count": {
"description": "max number of proxies per application.",
"type": "integer",
"format": "uint16",
"minimum": 0,
"maximum": 65535
},
"disallowed_endpoints": {
"description": "a list of any internal or external target\nregexes that should be disallowed.",
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"count",
"disallowed_endpoints"
]
},
"FunctionLimits": {
"type": "object",
"properties": {
"count": {
"description": "Max number of functions per app.",
"type": "integer",
"format": "uint8",
"minimum": 0,
"maximum": 255
},
"max_timeout": {
"description": "Function request timeout.\n\nUnit: seconds.",
"type": "integer",
"format": "uint16",
"minimum": 0,
"maximum": 65535
}
},
"required": [
"count",
"max_timeout"
]
},
"AuthLimits": {
"type": "object"
},
"MonitorLimits": {
"type": "object"
},
"StorageLimits": {
"type": "object",
"properties": {
"max_storage": {
"description": "Maximum total storage for all apps and api.\n\nUnit: bytes.\n\nDefault: 10 GB",
"type": "integer",
"format": "uint64",
"minimum": 0
},
"max_app_storage": {
"description": "Maximum per-app storage.\n\nUnit: bytes.\n\nDefault: 50 MB",
"type": "integer",
"format": "uint64",
"minimum": 0
},
"assets": {
"$ref": "#/$defs/AssetsLimits"
},
"artifact": {
"$ref": "#/$defs/ArtifactLimits"
},
"cache": {
"$ref": "#/$defs/CacheLimits"
},
"database": {
"$ref": "#/$defs/DatabaseLimits"
},
"secrets": {
"$ref": "#/$defs/SecretsLimits"
}
},
"required": [
"max_storage",
"max_app_storage",
"assets",
"artifact",
"cache",
"database",
"secrets"
]
},
"AssetsLimits": {
"type": "object",
"properties": {
"allowed_extensions": {
"description": "Allowed extensions corresponding to\n[MIME](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types) types.\n\n(More to be supported in the future)\n\nSupported:\n- \"txt\"\n- \"xml\"\n- \"html\"\n- \"css\"\n- \"css.map\"\n- \"csv\"\n- \"js\"\n- \"png\"\n- \"apng\"\n- \"gif\"\n- \"svg\"\n- \"jpg\"\n- \"jpeg\"\n- \"bmp\"\n- \"tif\"\n- \"tiff\"\n- \"webp\"\n- \"avif\"\n- \"ico\"\n- \"pdf\"\n- \"json\"\n- \"wasm\"\n\nSpecial:\n- \"none\" (for no extension; uses \"application/octet-stream\")\n- \"any\" (for unsupported extensions; also uses \"application/octet-stream\")",
"type": "array",
"items": {
"type": "string"
}
},
"max_store_size": {
"description": "Limit on total storage for all assets within an app\n(bytes).",
"type": "integer",
"format": "uint64",
"minimum": 0
},
"max_asset_size": {
"description": "Limit on individual asset size (bytes).",
"type": "integer",
"format": "uint64",
"minimum": 0
}
},
"required": [
"allowed_extensions",
"max_store_size",
"max_asset_size"
]
},
"ArtifactLimits": {
"type": "object",
"properties": {
"max_store_size": {
"type": "integer",
"format": "uint64",
"minimum": 0
},
"max_artifact_size": {
"type": "integer",
"format": "uint64",
"minimum": 0
}
},
"required": [
"max_store_size",
"max_artifact_size"
]
},
"CacheLimits": {
"type": "object",
"properties": {
"max_size_range": {
"type": "array",
"prefixItems": [
{
"type": "integer",
"format": "uint64",
"minimum": 0
},
{
"type": "integer",
"format": "uint64",
"minimum": 0
}
],
"minItems": 2,
"maxItems": 2
},
"max_count_range": {
"type": "array",
"prefixItems": [
{
"type": "integer",
"format": "uint",
"minimum": 0
},
{
"type": "integer",
"format": "uint",
"minimum": 0
}
],
"minItems": 2,
"maxItems": 2
}
},
"required": [
"max_size_range",
"max_count_range"
]
},
"DatabaseLimits": {
"type": "object",
"properties": {
"max_model_definitions": {
"type": "integer",
"format": "uint8",
"minimum": 0,
"maximum": 255
},
"max_model_fields": {
"type": "integer",
"format": "uint8",
"minimum": 0,
"maximum": 255
},
"max_item_size": {
"type": "integer",
"format": "uint64",
"minimum": 0
},
"max_field_size": {
"type": "integer",
"format": "uint64",
"minimum": 0
}
},
"required": [
"max_model_definitions",
"max_model_fields",
"max_item_size",
"max_field_size"
]
},
"SecretsLimits": {
"type": "object",
"properties": {
"max_count": {
"type": "integer",
"format": "uint8",
"minimum": 0,
"maximum": 255
},
"max_size": {
"type": "integer",
"format": "uint64",
"minimum": 0
}
},
"required": [
"max_count",
"max_size"
]
},
"ProxiedMetric": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"endpoint": {
"type": "string"
}
},
"required": [
"name",
"endpoint"
]
},
"OrdinaryHostExtensionConfig": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"operations": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/ExtensionOperationConfig"
}
}
},
"required": [
"name",
"operations"
]
},
"ExtensionOperationConfig": {
"type": "object",
"properties": {
"idx": {
"type": "integer",
"format": "uint16",
"minimum": 0,
"maximum": 65535
},
"input": {
"$ref": "#/$defs/Kind"
},
"output": {
"$ref": "#/$defs/Kind"
}
},
"required": [
"idx",
"input",
"output"
]
},
"Kind": {
"description": "Defines the types recognized by this framework.",
"oneOf": [
{
"description": "In the case of one-to-many the deletion of the\nparent reference causes a cascading delete (i.e if you have a user, chat, message\nrelationship structure, deletion of the user or the chat automatically\ndeletes messages owned by either).\n\nReferences must always be bidirectionally defined.",
"type": "object",
"properties": {
"Ref": {
"type": "object",
"properties": {
"model": {
"description": "name of model you're referencing.",
"type": "string"
},
"field": {
"description": "name of the field on the model.",
"type": "string"
},
"many": {
"description": "whether you have many of the referenced model.",
"type": [
"boolean",
"null"
]
}
},
"required": [
"model",
"field"
]
}
},
"required": [
"Ref"
],
"additionalProperties": false
},
{
"description": "null/void/undefined/None",
"type": "string",
"const": "Void"
},
{
"description": "boolean/true/false",
"type": "string",
"const": "Bool"
},
{
"description": "integers between",
"type": "string",
"const": "I8"
},
{
"description": "integers between",
"type": "string",
"const": "U8"
},
{
"description": "integers between",
"type": "string",
"const": "I16"
},
{
"description": "integers between",
"type": "string",
"const": "U16"
},
{
"description": "integers between",
"type": "string",
"const": "I32"
},
{
"description": "integers between",
"type": "string",
"const": "U32"
},
{
"description": "integers between",
"type": "string",
"const": "I64"
},
{
"description": "integers between",
"type": "string",
"const": "U64"
},
{
"description": "floats between",
"type": "string",
"const": "F32"
},
{
"description": "floats between",
"type": "string",
"const": "F64"
},
{
"description": "universal unique identifiers. 16 bytes\nor 36 characters.",
"type": "string",
"const": "Uuid"
},
{
"description": "must be a valid URL",
"type": "string",
"const": "Url"
},
{
"description": "unix timestamp",
"type": "object",
"properties": {
"Timestamp": {
"type": "object",
"properties": {
"unit": {
"$ref": "#/$defs/TimeUnit"
},
"fmt": {
"type": [
"string",
"null"
]
}
},
"required": [
"unit"
]
}
},
"required": [
"Timestamp"
],
"additionalProperties": false
},
{
"description": "array of bytes.",
"type": "string",
"const": "Blob"
},
{
"description": "text/string/characters.",
"type": "string",
"const": "String"
},
{
"description": "JSON formatted string.",
"type": "string",
"const": "Json"
},
{
"description": "Markdown formatted string",
"type": "string",
"const": "Markdown"
},
{
"description": "array of values.",
"type": "object",
"properties": {
"List": {
"type": "object",
"properties": {
"kind": {
"description": "the type for the values stored in the list.",
"$ref": "#/$defs/Kind"
}
},
"required": [
"kind"
]
}
},
"required": [
"List"
],
"additionalProperties": false
},
{
"description": "Select from a list of options. Stored as its u8 index value.",
"type": "object",
"properties": {
"Enum": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"opts": {
"type": "array",
"items": {
"$ref": "#/$defs/EnumOpt"
}
}
},
"required": [
"name",
"opts"
]
}
},
"required": [
"Enum"
],
"additionalProperties": false
},
{
"description": "complex kind with its own name and subfields.",
"type": "object",
"properties": {
"Object": {
"type": "object",
"properties": {
"name": {
"description": "the object definition's name.",
"type": "string"
},
"fields": {
"description": "nested subfields.",
"type": "array",
"items": {
"$ref": "#/$defs/Field"
}
}
},
"required": [
"name",
"fields"
]
}
},
"required": [
"Object"
],
"additionalProperties": false
}
]
},
"TimeUnit": {
"type": "string",
"enum": [
"Seconds"
]
},
"EnumOpt": {
"type": "object",
"properties": {
"idx": {
"type": "integer",
"format": "uint8",
"minimum": 0,
"maximum": 255
},
"name": {
"type": "string"
}
},
"required": [
"idx",
"name"
]
},
"Field": {
"description": "Fields are used to describe properties on a model,\nIO for functions/integrations and content definitions.",
"type": "object",
"properties": {
"idx": {
"description": "The index used for compact, vector based serialization.\nThe index is preserved even if the property name changes.\nEach field must be assigned an index value from 0-255, with\nno gaps (i.e. cannot go from 2 to 4 without also having a field\nwith an index of 3).",
"type": "integer",
"format": "uint8",
"minimum": 0,
"maximum": 255
},
"name": {
"description": "this is the name that is used when accessing a property in a template\nand will be the name that is used in the JSON serialized format.",
"type": "string"
},
"kind": {
"description": "the \"kind\" represents the type of the value that will\nbe stored or sent.",
"$ref": "#/$defs/Kind"
},
"indexed": {
"description": "Used for models and content definitions. Determines whether\nyou can access an object/item by this property. All items\nhave are automatically stored ID that can be used for look\nup if no properties are indexed.\n\nNote: `indexed` fields also have a uniqueness constraint.\n\n!! Important: only `String`, `Uuid` and `Url` kinds can be indexed",
"type": [
"boolean",
"null"
]
},
"queryable": {
"description": "Specifies whether field can be queried via Gte/Gt, Lte/Lt, Eq and `BeginsWith`.\n\n!! Important: only `Bool`, `String`, `Url`, `Uuid`, `Timestamp`, `U8/16/32/64`, `I8/16/32/64`,\n!! and `F32/64` kinds can be made queryable.",
"type": [
"boolean",
"null"
]
},
"mapping": {
"description": "Used for integrations, so that a property on the external\nresource's response can be renamed.",
"type": [
"string",
"null"
]
},
"doc": {
"description": "Optional message to hint to the user\nin an editor.",
"type": [
"string",
"null"
]
},
"compressed": {
"description": "Compresses the value of the field using the Zstd compression algorithm (level 4).\n\nNote: at some point in the future, compression levels and compression algorithm\nselection will be configurable.",
"type": [
"boolean",
"null"
]
},
"encrypted": {
"description": "Encrypts the field using `XChaCha20Poly1305`.\n\nNote: The storage encryption key is stored on the same\nserver as the data it's encrypting; anyone with full access\nto the server. This is mostly useful for protecting\nsensitive data in backups (assuming the key isn't stored with the\nbackup), and can potentially limit exposure in partial-access context\nstemming from a misconfiguration or a mistake in a multi-tenant scenario\n(i.e. for whatever reason tenant A's database contents is moved to tenant B's\ndirectory, without the keys also being shifted over).\n\n!! Important: this is not currently intended for storing *any* meaningfully\n!! sensitive data (e.g. SSNs, credit card numbers, passwords, encryption keys, etc.)\n!! use (or don't) at your own risk.",
"type": [
"boolean",
"null"
]
}
},
"required": [
"idx",
"name",
"kind"
]
}
}
}