API Definition¶
App Kernel Engine¶
Bootstraps and manages the FastAPI application. Initialises MongoDB, registers models as REST services, sets up security and locale middleware, and starts the Uvicorn server.
Example:
from appkernel import AppKernelEngine, Model, MongoRepository
from typing import Annotated
from appkernel import Required, Generator, create_uuid_generator
class User(Model, MongoRepository):
id: Annotated[str | None, Required(), Generator(create_uuid_generator('U'))] = None
name: Annotated[str | None, Required()] = None
kernel = AppKernelEngine('my-service')
kernel.register(User, methods=['GET', 'POST', 'PUT', 'DELETE'])
kernel.run()
- class appkernel.AppKernelEngine(app_id: str, app: FastAPI | None = None, root_url: str = '/', log_level: int = 10, cfg_dir: str | None = None, development: bool = False, enable_defaults: bool = True, http_client_config: HttpClientConfig | None = None)¶
- enable_cors(cfg: CorsConfig | None = None) AppKernelEngine¶
Enable CORS support for browser-based cross-origin clients.
Installs Starlette’s
CORSMiddlewarewith the provided configuration. Call this last in the middleware chain — middleware added last executes first, so CORS headers are set and preflight OPTIONS requests are resolved before security or rate-limiting checks run.- Parameters:
cfg – CORS configuration. Defaults to
CorsConfig()(emptyallow_originslist — same-origin only).- Raises:
ValueError – If
allow_origins=['*']andallow_credentials=Trueare combined (rejected by browsers).
Example:
kernel = AppKernelEngine('my-app', cfg_dir='./config') kernel.enable_security() kernel.enable_rate_limiting() kernel.enable_cors(CorsConfig( allow_origins=['https://app.example.com'], allow_credentials=False, ))
- Returns:
selffor fluent chaining.
- enable_file_storage(backend: Any = None, validation_chain: Any = None, url_base: str = '/files', tags: list[str] | None = None) AppKernelEngine¶
Register streaming file upload, download, and delete endpoints.
Instantiates a
FileServiceand mounts it at url_base. Four routes are added:POST {url_base}/— upload (multipart/form-data)GET {url_base}/{file_id}— metadata JSONGET {url_base}/{file_id}/content— binary download (streaming)DELETE {url_base}/{file_id}— delete file + metadata
- Parameters:
backend – A
StorageBackendinstance. Defaults toFilesystemBackendwriting to a./uploadsdirectory.validation_chain – Head of a
FileValidatorchain, orNoneto skip validation.url_base – URL prefix for the four routes. Defaults to
'/files'.tags – OpenAPI tags applied to all file routes.
- Returns:
selffor fluent chaining.
Example:
from appkernel import AppKernelEngine from appkernel.file_storage import ( FilesystemBackend, SizeValidator, MimeTypeValidator, ) kernel = AppKernelEngine('my-app', cfg_dir='./config') chain = SizeValidator(max_bytes=10 * 1024 * 1024) chain.set_next(MimeTypeValidator(['image/jpeg', 'image/png'])) kernel.enable_file_storage( backend=FilesystemBackend('/var/uploads'), validation_chain=chain, url_base='/files', )
- enable_openapi(title: str | None = None, version: str = '1.0.0', description: str = '', include_docs: bool = True) AppKernelEngine¶
Register
/openapi.jsonand optionally/docsand/redocendpoints.Must be called after all services have been registered so the service registry is fully populated when the spec is first requested.
- Parameters:
title – API title shown in the spec and UI. Defaults to
app_id.version – Semantic version string for
info.version.description – Optional API-level description shown in the UI.
include_docs – When
True(default), also register Swagger UI at/docsand ReDoc at/redoc.
- Returns:
selffor fluent chaining.
Example:
kernel = AppKernelEngine('my-app', cfg_dir='./config') kernel.register(User, methods=['GET', 'POST', 'PUT', 'DELETE']) kernel.enable_openapi(title='My API', version='2.0.0')
- enable_rate_limiting(cfg: RateLimitConfig | None = None) AppKernelEngine¶
Enable in-process fixed-window rate limiting.
Call this after
enable_security()so that the rate-limit middleware is added last and therefore executes first — throttling requests before JWT validation is attempted.- Parameters:
cfg – Pool and window settings. Defaults to
RateLimitConfig()(medium-traffic profile: 100 req / 60 s per client IP).- Returns:
selffor fluent chaining.
Example:
from appkernel import AppKernelEngine, RateLimitConfig kernel = AppKernelEngine('my-app', cfg_dir='./config') kernel.enable_security() kernel.enable_rate_limiting( RateLimitConfig( requests_per_window=100, window_seconds=60, endpoint_limits={'/auth': 10}, exclude_paths=['/health'], ) )
- register(service_class_or_instance: type | object, url_base: str | None = None, methods: list[str] | None = None, enable_hateoas: bool = True, tags: list[str] | None = None) ResourceController¶
Register a Model class or service instance as a set of REST endpoints.
- Parameters:
service_class_or_instance – A
Modelsubclass for automatic CRUD, or a plain service instance decorated with@resource/@actionmethods.url_base – URL prefix for all generated routes (e.g.
'/v1/'). Defaults to the engine’sroot_url.methods – HTTP methods to expose for CRUD models (e.g.
['GET', 'POST', 'PUT', 'PATCH', 'DELETE']). Defaults to['GET'].enable_hateoas – Include
_linksin responses. Defaults toTrue.tags –
OpenAPI tag strings applied to every endpoint registered for this service. Merged with per-decorator
tags(registration tags come first, decorator tags appended). Useful for grouping all endpoints of a version together:kernel.register(UserV1Service(), url_base='/v1/', tags=['v1']) kernel.register(UserV2Service(), url_base='/v2/', tags=['v2'])
- Returns:
ResourceControllerfor fluent RBAC chaining.
Model¶
The base class for all domain objects. Provides JSON serialisation, metadata generation, validation,
and list manipulation helpers. Extend with MongoRepository or AuditableRepository
for persistence.
- class appkernel.Model(**kwargs: Any)¶
The base class of all Model objects which are intended to be persisted in the database or served via REST. Built on Pydantic BaseModel.
- copy(*, include: AbstractSetIntStr | MappingIntStrAny | None = None, exclude: AbstractSetIntStr | MappingIntStrAny | None = None, update: Dict[str, Any] | None = None, deep: bool = False) Self¶
Returns a copy of the model.
- !!! warning “Deprecated”
This method is now deprecated; use model_copy instead.
If you need include or exclude, use:
`python {test="skip" lint="skip"} data = self.model_dump(include=include, exclude=exclude, round_trip=True) data = {**data, **(update or {})} copied = self.model_validate(data) `- Parameters:
include – Optional set or mapping specifying which fields to include in the copied model.
exclude – Optional set or mapping specifying which fields to exclude in the copied model.
update – Optional dictionary of field-value pairs to override field values in the copied model.
deep – If True, the values of fields that are Pydantic models will be deep-copied.
- Returns:
A copy of the model with included, excluded and updated fields as specified.
- finalise_and_validate() None¶
Runs generators, defaults, converters, and validators. Called before persistence (save/to_dict).
- model_config = {'arbitrary_types_allowed': True, 'extra': 'allow', 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- classmethod model_construct(_fields_set: set[str] | None = None, **values: Any) Self¶
Creates a new instance of the Model class with validated data.
Creates a new model setting __dict__ and __pydantic_fields_set__ from trusted or pre-validated data. Default values are respected, but no other validation is performed.
- !!! note
model_construct() generally respects the model_config.extra setting on the provided model. That is, if model_config.extra == ‘allow’, then all extra passed values are added to the model instance’s __dict__ and __pydantic_extra__ fields. If model_config.extra == ‘ignore’ (the default), then all extra passed values are ignored. Because no validation is performed with a call to model_construct(), having model_config.extra == ‘forbid’ does not result in an error if extra values are passed, but they will be ignored.
- Parameters:
_fields_set – A set of field names that were originally explicitly set during instantiation. If provided, this is directly used for the [model_fields_set][pydantic.BaseModel.model_fields_set] attribute. Otherwise, the field names from the values argument will be used.
values – Trusted or pre-validated data dictionary.
- Returns:
A new instance of the Model class with validated data.
- model_copy(*, update: Mapping[str, Any] | None = None, deep: bool = False) Self¶
- !!! abstract “Usage Documentation”
[model_copy](../concepts/models.md#model-copy)
Returns a copy of the model.
- !!! note
The underlying instance’s [__dict__][object.__dict__] attribute is copied. This might have unexpected side effects if you store anything in it, on top of the model fields (e.g. the value of [cached properties][functools.cached_property]).
- Parameters:
update – Values to change/add in the new model. Note: the data is not validated before creating the new model. You should trust this data.
deep – Set to True to make a deep copy of the model.
- Returns:
New model instance.
- model_dump(*, mode: Literal['json', 'python'] | str = 'python', include: set[int] | set[str] | Mapping[int, set[int] | set[str] | Mapping[int, IncEx | bool] | Mapping[str, IncEx | bool] | bool] | Mapping[str, set[int] | set[str] | Mapping[int, IncEx | bool] | Mapping[str, IncEx | bool] | bool] | None = None, exclude: set[int] | set[str] | Mapping[int, set[int] | set[str] | Mapping[int, IncEx | bool] | Mapping[str, IncEx | bool] | bool] | Mapping[str, set[int] | set[str] | Mapping[int, IncEx | bool] | Mapping[str, IncEx | bool] | bool] | None = None, context: Any | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal['none', 'warn', 'error'] = True, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False) dict[str, Any]¶
- !!! abstract “Usage Documentation”
[model_dump](../concepts/serialization.md#python-mode)
Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.
- Parameters:
mode – The mode in which to_python should run. If mode is ‘json’, the output will only contain JSON serializable types. If mode is ‘python’, the output may contain non-JSON-serializable Python objects.
include – A set of fields to include in the output.
exclude – A set of fields to exclude from the output.
context – Additional context to pass to the serializer.
by_alias – Whether to use the field’s alias in the dictionary key if defined.
exclude_unset – Whether to exclude fields that have not been explicitly set.
exclude_defaults – Whether to exclude fields that are set to their default value.
exclude_none – Whether to exclude fields that have a value of None.
exclude_computed_fields – Whether to exclude computed fields. While this can be useful for round-tripping, it is usually recommended to use the dedicated round_trip parameter instead.
round_trip – If True, dumped values should be valid as input for non-idempotent types such as Json[T].
warnings – How to handle serialization errors. False/”none” ignores them, True/”warn” logs errors, “error” raises a [PydanticSerializationError][pydantic_core.PydanticSerializationError].
fallback – A function to call when an unknown value is encountered. If not provided, a [PydanticSerializationError][pydantic_core.PydanticSerializationError] error is raised.
serialize_as_any – Whether to serialize fields with duck-typing serialization behavior.
- Returns:
A dictionary representation of the model.
- model_dump_json(*, indent: int | None = None, ensure_ascii: bool = False, include: set[int] | set[str] | Mapping[int, set[int] | set[str] | Mapping[int, IncEx | bool] | Mapping[str, IncEx | bool] | bool] | Mapping[str, set[int] | set[str] | Mapping[int, IncEx | bool] | Mapping[str, IncEx | bool] | bool] | None = None, exclude: set[int] | set[str] | Mapping[int, set[int] | set[str] | Mapping[int, IncEx | bool] | Mapping[str, IncEx | bool] | bool] | Mapping[str, set[int] | set[str] | Mapping[int, IncEx | bool] | Mapping[str, IncEx | bool] | bool] | None = None, context: Any | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal['none', 'warn', 'error'] = True, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False) str¶
- !!! abstract “Usage Documentation”
[model_dump_json](../concepts/serialization.md#json-mode)
Generates a JSON representation of the model using Pydantic’s to_json method.
- Parameters:
indent – Indentation to use in the JSON output. If None is passed, the output will be compact.
ensure_ascii – If True, the output is guaranteed to have all incoming non-ASCII characters escaped. If False (the default), these characters will be output as-is.
include – Field(s) to include in the JSON output.
exclude – Field(s) to exclude from the JSON output.
context – Additional context to pass to the serializer.
by_alias – Whether to serialize using field aliases.
exclude_unset – Whether to exclude fields that have not been explicitly set.
exclude_defaults – Whether to exclude fields that are set to their default value.
exclude_none – Whether to exclude fields that have a value of None.
exclude_computed_fields – Whether to exclude computed fields. While this can be useful for round-tripping, it is usually recommended to use the dedicated round_trip parameter instead.
round_trip – If True, dumped values should be valid as input for non-idempotent types such as Json[T].
warnings – How to handle serialization errors. False/”none” ignores them, True/”warn” logs errors, “error” raises a [PydanticSerializationError][pydantic_core.PydanticSerializationError].
fallback – A function to call when an unknown value is encountered. If not provided, a [PydanticSerializationError][pydantic_core.PydanticSerializationError] error is raised.
serialize_as_any – Whether to serialize fields with duck-typing serialization behavior.
- Returns:
A JSON string representation of the model.
- property model_extra: dict[str, Any] | None¶
Get extra fields set during validation.
- Returns:
A dictionary of extra fields, or None if config.extra is not set to “allow”.
- property model_fields_set: set[str]¶
Returns the set of fields that have been explicitly set on this model instance.
- Returns:
- A set of strings representing the fields that have been set,
i.e. that were not filled from defaults.
- classmethod model_json_schema(by_alias: bool = True, ref_template: str = '#/$defs/{model}', schema_generator: type[GenerateJsonSchema] = <class 'pydantic.json_schema.GenerateJsonSchema'>, mode: Literal['validation', 'serialization']='validation', *, union_format: Literal['any_of', 'primitive_type_array']='any_of') dict[str, Any]¶
Generates a JSON schema for a model class.
- Parameters:
by_alias – Whether to use attribute aliases or not.
ref_template – The reference template.
union_format –
The format to use when combining schemas from unions together. Can be one of:
’any_of’: Use the [anyOf](https://json-schema.org/understanding-json-schema/reference/combining#anyOf)
keyword to combine schemas (the default). - ‘primitive_type_array’: Use the [type](https://json-schema.org/understanding-json-schema/reference/type) keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive type (string, boolean, null, integer or number) or contains constraints/metadata, falls back to any_of.
schema_generator – To override the logic used to generate the JSON schema, as a subclass of GenerateJsonSchema with your desired modifications
mode – The mode in which to generate the schema.
- Returns:
The JSON schema for the given model class.
- classmethod model_parametrized_name(params: tuple[type[Any], ...]) str¶
Compute the class name for parametrizations of generic classes.
This method can be overridden to achieve a custom naming scheme for generic BaseModels.
- Parameters:
params – Tuple of types of the class. Given a generic class Model with 2 type variables and a concrete model Model[str, int], the value (str, int) would be passed to params.
- Returns:
String representing the new class where params are passed to cls as type variables.
- Raises:
TypeError – Raised when trying to generate concrete names for non-generic models.
- model_post_init(context: Any, /) None¶
Override this method to perform additional initialization after __init__ and model_construct. This is useful if you want to do some validation that requires the entire model to be initialized.
- classmethod model_rebuild(*, force: bool = False, raise_errors: bool = True, _parent_namespace_depth: int = 2, _types_namespace: MappingNamespace | None = None) bool | None¶
Try to rebuild the pydantic-core schema for the model.
This may be necessary when one of the annotations is a ForwardRef which could not be resolved during the initial attempt to build the schema, and automatic rebuilding fails.
- Parameters:
force – Whether to force the rebuilding of the model schema, defaults to False.
raise_errors – Whether to raise errors, defaults to True.
_parent_namespace_depth – The depth level of the parent namespace, defaults to 2.
_types_namespace – The types namespace, defaults to None.
- Returns:
Returns None if the schema is already “complete” and rebuilding was not required. If rebuilding _was_ required, returns True if rebuilding was successful, otherwise False.
- classmethod model_validate(obj: Any, *, strict: bool | None = None, extra: Literal['allow', 'ignore', 'forbid'] | None = None, from_attributes: bool | None = None, context: Any | None = None, by_alias: bool | None = None, by_name: bool | None = None) Self¶
Validate a pydantic model instance.
- Parameters:
obj – The object to validate.
strict – Whether to enforce types strictly.
extra – Whether to ignore, allow, or forbid extra data during model validation. See the [extra configuration value][pydantic.ConfigDict.extra] for details.
from_attributes – Whether to extract data from object attributes.
context – Additional context to pass to the validator.
by_alias – Whether to use the field’s alias when validating against the provided input data.
by_name – Whether to use the field’s name when validating against the provided input data.
- Raises:
ValidationError – If the object could not be validated.
- Returns:
The validated model instance.
- classmethod model_validate_json(json_data: str | bytes | bytearray, *, strict: bool | None = None, extra: Literal['allow', 'ignore', 'forbid'] | None = None, context: Any | None = None, by_alias: bool | None = None, by_name: bool | None = None) Self¶
- !!! abstract “Usage Documentation”
[JSON Parsing](../concepts/json.md#json-parsing)
Validate the given JSON data against the Pydantic model.
- Parameters:
json_data – The JSON data to validate.
strict – Whether to enforce types strictly.
extra – Whether to ignore, allow, or forbid extra data during model validation. See the [extra configuration value][pydantic.ConfigDict.extra] for details.
context – Extra variables to pass to the validator.
by_alias – Whether to use the field’s alias when validating against the provided input data.
by_name – Whether to use the field’s name when validating against the provided input data.
- Returns:
The validated Pydantic model.
- Raises:
ValidationError – If json_data is not a JSON string or the object could not be validated.
- classmethod model_validate_strings(obj: Any, *, strict: bool | None = None, extra: Literal['allow', 'ignore', 'forbid'] | None = None, context: Any | None = None, by_alias: bool | None = None, by_name: bool | None = None) Self¶
Validate the given object with string data against the Pydantic model.
- Parameters:
obj – The object containing string data to validate.
strict – Whether to enforce types strictly.
extra – Whether to ignore, allow, or forbid extra data during model validation. See the [extra configuration value][pydantic.ConfigDict.extra] for details.
context – Extra variables to pass to the validator.
by_alias – Whether to use the field’s alias when validating against the provided input data.
by_name – Whether to use the field’s name when validating against the provided input data.
- Returns:
The validated Pydantic model.
Field Metadata¶
Fields are declared using Python’s typing.Annotated with one or more metadata markers.
All fields should default to None — the deferred validation pattern runs validation explicitly
via finalise_and_validate() or implicitly via save() / dumps().
Example:
from typing import Annotated
from pydantic import Field
from appkernel import Required, Generator, Converter, Default, Validators, Marshal
from appkernel import MongoIndex, MongoUniqueIndex, MongoTextIndex
from appkernel import create_uuid_generator, content_hasher, Email, NotEmpty
class User(Model, MongoRepository):
id: Annotated[str | None, Required(), Generator(create_uuid_generator('U'))] = None
name: Annotated[str | None, Required(), MongoUniqueIndex()] = None
email: Annotated[str | None, Validators(Email), MongoUniqueIndex()] = None
password: Annotated[str | None, Validators(NotEmpty), Converter(content_hasher()), Field(exclude=True)] = None
Required marker¶
- class appkernel.Required¶
Marks a field as required. Checked by finalise_and_validate().
Generator marker¶
- class appkernel.Generator(func: Callable)¶
Auto-generate field value when None at validation time.
Converter marker¶
- class appkernel.Converter(func: Callable)¶
Convert field value during finalise_and_validate().
Default marker¶
- class appkernel.Default(value: Any)¶
Default value applied when field is None at validation time.
Validators marker¶
- class appkernel.Validators(*validators)¶
List of AppKernel Validator instances for validation and parameter spec.
Marshal marker¶
- class appkernel.Marshal(marshaller: Any)¶
Bidirectional wire-format converter (Marshaller class or instance).
MongoDB index markers¶
- class appkernel.MongoIndex(sort_order: SortOrder = SortOrder.ASC)¶
Regular MongoDB index on a field.
- class appkernel.MongoUniqueIndex(sort_order: SortOrder = SortOrder.ASC)¶
Unique constraint index.
- class appkernel.MongoTextIndex(sort_order: SortOrder = SortOrder.ASC)¶
Full-text search index.
Validators¶
The base Validator class¶
- class appkernel.Validator(validator_type: ValidatorType, value: Any = None, message: str | None = None)¶
a root object for different type of validators
- __init__(validator_type: ValidatorType, value: Any = None, message: str | None = None) None¶
- validate(parameter_name: str, validable_object: Any) None¶
Validates and object against the validation parameters.
- Parameters:
parameter_name
validable_object
- Raises:
ValidationException –
Not Empty¶
- class appkernel.NotEmpty¶
Used for string types to make sure that there’s a string with length longer than 0. Also checks lists for a size.
- __init__() None¶
- validate(parameter_name: str, validable_object: Any) None¶
Validates and object against the validation parameters.
- Parameters:
parameter_name
validable_object
- Raises:
ValidationException –
Regular Expression¶
Email¶
- class appkernel.Email¶
It is a convenience validator extending the Regexp validator and initialising it with an e-mail regular expression.
- __init__() None¶
- validate(parameter_name: str, validable_object: Any) None¶
Validates and object against the validation parameters.
- Parameters:
parameter_name
validable_object
- Raises:
ValidationException –
Minimum¶
Maximum¶
Past¶
Future¶
Unique¶
Generators¶
UUID Generator¶
- appkernel.create_uuid_generator(prefix: str | None = None) Callable[[], str]¶
Date generator¶
- appkernel.date_now_generator() datetime¶
Password hasher¶
- appkernel.content_hasher(rounds: int = 12) Callable[[str], str]¶
Repository¶
- class appkernel.Repository¶
Query¶
MongoRepository¶
- class appkernel.MongoRepository¶
- async classmethod aggregate(pipe: list[dict[str, Any]] = [], allow_disk_use: bool = True, batch_size: int = 100, max_results: int | None = 10000, trusted: bool = False) list[dict[str, Any]]¶
Run an aggregation pipeline.
- Parameters:
pipe – Aggregation stages. When called over HTTP (
trusted=False), only stages in_HTTP_ALLOWED_STAGESare permitted. Cross-collection stages ($lookup,$graphLookup,$unionWith) and write/JS stages are always blocked from HTTP.trusted – Set to
Truefor internal application code that constructs the pipeline itself. Bypasses the HTTP stage allowlist while still blocking$out,$merge,$function, and$accumulator.max_results – Caps the result set by appending a
$limitstage. PassNoneto disable for pipelines with a bounded result (e.g. those already containing$limitor$count).
- classmethod stream_by_query(query: dict[str, Any], batch_size: int = 500) AsyncGenerator[Model, None]¶
Async generator that streams all matching documents in batches without loading the full result set into memory. Use for bulk processing, exports, and migrations where create_cursor_by_query’s page limit is not appropriate.
Auditable Repository¶
- class appkernel.AuditableRepository(**kwargs: Any)¶