Security architecture¶
Talea treats external input as hostile while treating application declarations, callbacks, codecs, and ordinary Python execution as trusted code.
Trust boundaries¶
| Surface | Talea governs | Caller still owns |
|---|---|---|
| default JSON decode | size, duplicate keys, non-standard numbers, parse failures | transport deadlines and upstream limits |
| Mapping/JSON conversion | depth, node work, aggregated errors, cycles | behavior of custom Mapping implementations |
| strict construction/validation | schema correctness | whether the caller's Python object is trusted |
| callbacks and serializers | conversion of raised failures into safe Talea errors where documented | callback side effects, blocking, I/O, secret logging |
| custom codecs | Talea projection after/before codec boundary | codec safety, CPU, memory, exceptions |
| regex constraints | declaration-time compilation and safe binding | catastrophic backtracking; no timeout is provided |
| output and schema tooling | cycle rejection and explicit projection failures | output size and tooling resource budgets |
| dataclass Contract | declared stored fields, exact identity, structured boundaries | constructor, post-init, descriptors, generated repr |
| nested output selection | canonical schema validation, immutable normalization, direct projection | authorization to request or disclose fields |
| represented custom values | declared input/output result validation, exact-once callback transport, Sensitive error policy | callback CPU, memory, mutation, I/O, logging, and output amplification |
| declared serializer output | complete result validation, exact-once callback transport, callback-free schema/selection discovery, Sensitive cause suppression | callback CPU, memory, mutation, reentrancy, I/O, logging, and output amplification |
The finite default policy is 8 MiB JSON transport, depth 64, 100,000 compiled node visits, and 100 aggregated errors. It reduces Talea-owned unbounded work; it is not a denial-of-service prevention guarantee.
Generated code safety¶
Generated source comes only from compiler templates. User values are bound as globals. Dynamic class/module/qualified names are normalized and validated; pattern text and aliases are not inserted into source. Repository tests cover quotes, newlines, malicious-looking names, aliases, patterns, and callback identities.
Nested selector keys are treated as data and validated against canonical field
truth before compilation. Caller-owned dictionaries and sets are copied into
an immutable tree before field access. There is no global selector cache; each
Spec class retains at most 32 immutable compiled plans and evicts the oldest
selected plan on overflow. Very broad or deep selectors can still consume
caller-owned output CPU and memory under normal Python limits;
ResourcePolicy intentionally governs hostile input, not application-owned
output.
Annotation resolution uses Python's supported annotation machinery and retained definition namespaces. Talea does not provide an API that evaluates arbitrary untrusted annotation strings. Application class bodies and imported modules are trusted Python code, as they are for any annotation-driven library.
Sensitive data¶
Sensitive redacts Talea-owned validation and serialization failures, Spec
representation, and retained callback causes under the marked boundary. It does
not omit values from successful serialization. WriteOnly remains distinct:
ordinary source Specs still serialize it, while an explicitly derived output
Spec structurally excludes it. Likewise, an input-derived Spec structurally
excludes ReadOnly fields. The derived classes are contract shapes, not access
control: the application still owns authentication, authorization, persistence
permissions, and output selection at each endpoint.
Directional selection uses normalized canonical field metadata during class
derivation. Removed fields have no constructor slot, alias, Mapping/JSON input
path, serializer hook, repr entry, introspection field, or schema property on
that derived class. Input partials may patch their exact source; output partials
are rejected by apply_patch so read-only values cannot re-enter through a
read-oriented view. Nested Specs are not recursively rewritten, so applications
must explicitly derive nested boundary shapes when required.
include and exclude control output projection only. They do not establish
the caller's identity, role, tenant, consent, or permission to see a field.
Applications must authorize the chosen projection before serialization;
Sensitive is failure-redaction metadata, not an output access-control rule.
For dataclasses, Talea cannot control the class's own generated repr without
mutating the application type. A sensitive dataclass field may therefore appear
in ordinary repr(instance) even though Talea-owned failures redact it. Use
dataclasses.field(repr=False) when the application representation must omit
that value. Dataclass constructors, __post_init__, custom __getattribute__,
and declared descriptors are trusted application execution, not sandboxed
input machinery.
Representation callbacks are subject to the same trust boundary. They are
synchronous and may reenter Talea, but compilation/publication locks are not
held while they execute. ResourcePolicy covers external input traversal, not
callback work or output size. See Custom domain
representations for the full contract.
At a Sensitive represented input boundary, Talea normalizes ordinary loader
exceptions into a redacted ValidationError with no retained cause; a
non-sensitive loader still uses ValueError as its declared rejection signal
and propagates other application defects.
Declared serializer output contracts prevent a callback result from drifting
from published output schema, but they do not sandbox the callback. Talea
normalizes invalid nested selectors before invoking application code and never
invokes a serializer for JSON Schema, OpenAPI, or introspection. Callback
exceptions and invalid declared results at a Sensitive boundary suppress unsafe
causes. A callback may still mutate its source, reenter serialization, return a
huge graph, or log secrets; output remains outside input ResourcePolicy
governance.
Supply chain¶
pyproject.toml declares dependencies = []: Talea has zero required runtime
dependencies and production code is pure Python. Tests, benchmarks, typing,
builds, and documentation use third-party development tools. This narrows the
runtime supply-chain surface but is not a general security certification.
See ResourcePolicy for operation details and Known limitations for ungoverned surfaces.
Review concrete attacks, not only controls¶
The executable hostile-input scenarios cover oversized JSON before decoding, excessive depth, exhausted work nodes, truncated broad invalid input, secret-bearing errors, and custom Mapping code. They demonstrate both the bounded Talea behavior and the point where arbitrary Python remains outside the library's control.
For an application review, ask which endpoints can receive the contract, what
the largest valid shape is, whether upstream transport limits run before a
complete body is allocated, which callback/codec/pattern code executes, where
errors() and repr are logged, and which output type allow-lists secrets. Test
those answers with production-shaped payloads rather than relying on default
numbers alone.
Talea does not claim regulatory compliance, process isolation, deadline enforcement, safe untrusted pickle, safe arbitrary regular expressions, or safe execution of user callbacks. Zero required runtime dependencies narrows one supply-chain dimension; it does not replace provenance, signed releases, dependency review for development/build tools, or the embedding application's threat model.