Core¶
Shared domain models, base types, and enums used across the framework.
Types¶
types
¶
Reusable Pydantic type annotations and validators.
CurrencyCode intentionally lives in synthorg.budget.currency
next to the ISO 4217 allowlist data. Importing it here would force
core to depend on budget, introducing a circular import via
the many budget modules that already import from core.types.
Consumers who need the validated currency type import it from
synthorg.budget.currency.
CapabilityLevel
module-attribute
¶
What a model can be trusted with: expert (hardest work) >
capable > basic. Declared weakest-first, because that order is what
:data:CAPABILITY_LADDER reads as the rank.
A claim about capability, never about size or price. The two are only ever
correlated, and grading by the proxy is how a large older model came to
outrank a smaller newer one that benchmarked above it. Locality is a
separate axis with its own signal, so a small model an operator runs
themselves is basic and local, not a fourth rung.
Never order these with < / >. That the three words happen to sort
alphabetically into rank order is a coincidence of this vocabulary, not a
property of it; go through :func:capability_rank or
:func:capability_meets.
AutonomyDetailLevel
module-attribute
¶
Level of autonomy instruction detail in prompt profiles.
PersonalityMode
module-attribute
¶
Personality section verbosity in prompt profiles.
NotBlankStr
module-attribute
¶
NotBlankStr = Annotated[
str, StringConstraints(min_length=1), AfterValidator(_check_not_whitespace)
]
A string that must be non-empty and not consist solely of whitespace.
PersonaLabelStr
module-attribute
¶
PersonaLabelStr = Annotated[
str,
BeforeValidator(flatten_label),
StringConstraints(min_length=1),
AfterValidator(_check_not_whitespace),
]
A persona-bound label (role / department / name): flattened to a single line with angle brackets stripped at construction, then required non-blank. Source-side defence-in-depth for prompt-injection (the render sites also flatten); a value that is empty after flattening is rejected.
capability_rank
¶
capability_meets
¶
Return whether candidate is at least as capable as required.
capability_below
¶
Return the rung immediately below level.
Returns:
| Type | Description |
|---|---|
CapabilityLevel | None
|
The next weaker rung, or |
CapabilityLevel | None
|
there is nothing cheaper to descend to. |
Source code in src/synthorg/core/types.py
require_not_blank
¶
Validate a plain string arg is non-blank at runtime.
A NotBlankStr annotation only runs inside a Pydantic model, so a
domain-exception __init__ typed execution_id: NotBlankStr would
still accept "". Call this in such constructors to enforce the
contract and name the offending field.
Returns:
| Type | Description |
|---|---|
str
|
The unchanged value once confirmed non-blank. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is empty or whitespace-only. |
Source code in src/synthorg/core/types.py
flatten_label
¶
Flatten a semi-trusted label for safe interpolation into a prompt.
Collapses all whitespace (newlines included) onto one line and drops
angle brackets so a crafted value cannot forge an untrusted-content
fence or inject a fresh instruction line into a SYSTEM prompt. Shared
by the persona renderer, the chief-of-staff router, and the
PersonaLabelStr field type so the sanitisation cannot drift
between sink and source.
Returns:
| Type | Description |
|---|---|
str
|
The single-line, angle-bracket-free label. |
Source code in src/synthorg/core/types.py
stable_agent_id
¶
Derive a deterministic agent id from an agent name.
The config-sourced agent roster and the runtime registry both derive
identity from the agent name without coordinating, so a config agent
and its registered AgentIdentity resolve to the same id and the
dashboard can address either by one stable UUID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Agent display name (unique across the company config). |
required |
Returns:
| Type | Description |
|---|---|
UUID
|
The deterministic |
Source code in src/synthorg/core/types.py
validate_unique_strings
¶
Validate that every string in values is unique.
Raises:
| Type | Description |
|---|---|
ValueError
|
If duplicates are present. |
Source code in src/synthorg/core/types.py
Enums¶
Domain enums co-locate with the package that owns them. Foundation enums
that core models depend on stay core-local: the task family (status, type,
priority, complexity, stakes, structure, topology, source) plus stakes
ordering in synthorg.core.task_enums; project status and the git-backend
/ environment discriminators in synthorg.core.project_enums; autonomy
level and ordering in synthorg.core.autonomy_enums; tool access level in
synthorg.core.tool_constraints; agent memory level and category in
synthorg.core.memory_enums; the model completion-outcome (finish reason) in
synthorg.core.completion_enums; and artifact type in synthorg.core.artifact
(all below). The cross-cutting value objects EffectiveAutonomy (resolved
autonomy) and RedTeamReviewInput (red-team gate input) also live core-local,
in synthorg.core.effective_autonomy and synthorg.core.redteam_review_input,
so engine, security, and tools consumers reference them without dragging a heavy
hub at import time. Every other domain enum lives with its owning package: agent
status, the personality traits (risk tolerance, creativity, decision style,
collaboration preference, communication verbosity, conflict approach), cost
tier, and strategic output mode under HR; company type
and department name under Organisation; the skill-pattern
taxonomy under Templates; memory consolidation interval and
org-fact category under Memory; knowledge source type, content
kind, and source status under Knowledge; research source
type, claim type, and run status under Research;
living-document type under Docs Engine; the workflow
enums, workspace merge enums (order, escalation, conflict type), operator
intervention kind, and the agent-runtime execution, recovery, and decision
enums under Engine; the conversation turn, status, and proposal
enums under Communication; the charter status enum under
Meta; approval status, risk level, and source in
synthorg.approval.enums (below); and the security action-type taxonomy,
tool category, autonomy-downgrade reason, and timeout-action type under
Security.
Task Enums¶
task_enums
¶
Task-family enumerations and stakes ordering.
TaskStatus
¶
Bases: StrEnum
Lifecycle status of a task.
The authoritative transition map lives in
synthorg.core.task_transitions.VALID_TRANSITIONS.
Summary for quick reference:
CREATED -> ASSIGNED | BLOCKED (nobody to route it to) | REJECTED
| FAILED (planning failed before assignment)
ASSIGNED -> IN_PROGRESS | AUTH_REQUIRED | BLOCKED | CANCELLED
| FAILED | INTERRUPTED | SUSPENDED
IN_PROGRESS -> IN_REVIEW | AWAITING_INPUT | AUTH_REQUIRED | BLOCKED
| CANCELLED | FAILED | INTERRUPTED | SUSPENDED
IN_REVIEW -> COMPLETED | IN_PROGRESS (rework) | BLOCKED | CANCELLED
AWAITING_INPUT -> IN_PROGRESS (answer supplied) | CANCELLED (abandoned)
AUTH_REQUIRED -> ASSIGNED (approved) | CANCELLED (denied/timeout)
BLOCKED -> ASSIGNED (unblocked) | IN_REVIEW (an escalated review's
answer rejoins it) | CANCELLED (abandoned)
FAILED -> ASSIGNED (reassignment for retry) | CANCELLED (abandoned)
INTERRUPTED -> ASSIGNED (reassignment on restart) | CANCELLED
SUSPENDED -> ASSIGNED (resume from checkpoint) | CANCELLED
COMPLETED, CANCELLED, and REJECTED are terminal states.
FAILED, INTERRUPTED, and SUSPENDED are non-terminal (can be reassigned).
AUTH_REQUIRED and AWAITING_INPUT are non-terminal (waiting on a human).
BlockedReason
¶
Bases: StrEnum
Why a task is parked at :attr:TaskStatus.BLOCKED.
BLOCKED is reached from several directions that mean different
things, and the status alone cannot tell them apart. A completion
review that escalates parks the task for a human; a coordination wave
releasing a subtask nobody will run parks it for a scheduler. Reading
the status alone, a rule written for the first silently applies to the
second, which is how a task blocked by a wave release came to skip the
verification the review gate exists to impose.
Absent (None) means the writer did not say. It is not a synonym for
any member here, and no rule may treat it as one.
ParkExit
¶
Bases: StrEnum
Who can end a park, and therefore who the org is waiting on.
BLOCKED says a task stopped. It never says whether anything will
start it again, and every rule needing that answer was carrying its own
list of reasons. The lists disagreed, and the quieter one won: the stall
classifier counted an escalated review as dead, so a live run replanned
the initiative half a second after asking a human to decide it, and
superseded the plan the question was about.
OPERATOR: a decision is open in front of a person, and the exit is
theirs to take. Replanning does not answer them, it discards the question.
SWEEP: a reconciler releases it with nobody asked, so the org is
waiting on itself and a replan would race what is already coming.
REPLAN: nothing here will move it. The work is still wanted, but
only a new plan can order it, so this is the one that means dead.
TaskType
¶
Bases: StrEnum
Classification of the kind of work a task represents.
Priority
¶
Bases: StrEnum
Task urgency and importance level.
Complexity
¶
Bases: StrEnum
Estimated task complexity.
Stakes
¶
Bases: StrEnum
How consequential a subtask or task is for capability-based agent selection.
Distinct from :class:Priority (urgency/importance) and
:class:Complexity (effort): stakes captures the cost of being
wrong. Low-stakes work tolerates a cheap model; high-stakes work
(architecture, irreversible decisions) warrants a strong model and
an adversarial red-team review. The authoritative ordering lives in
STAKES_ORDER below.
TaskStructure
¶
Bases: StrEnum
Classification of how a task's subtasks relate to each other.
Used by the decomposition engine to determine coordination topology and execution ordering. See the Engine design page.
AUTO is the unresolved state, not a fourth shape: it says a planner
declared no structure and something downstream must decide one. It is
distinct from SEQUENTIAL precisely so a deliberate sequential
declaration cannot be mistaken for silence, which is what lets the
classifier fill only a genuine gap. Nothing accepts it as an answer:
DecompositionResult and the plan mapping both refuse it.
CoordinationTopology
¶
Bases: StrEnum
Coordination topology for multi-agent task execution.
Determines how agents coordinate when executing decomposed subtasks. See the Engine design page.
TaskSource
¶
Bases: StrEnum
Origin of a task within the system.
Distinguishes tasks created internally by agents from those originating from client simulation or external API calls.
compare_stakes
¶
Compare two stakes levels.
Returns negative if a is lower-stakes than b, zero if equal, positive if a is higher-stakes than b.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
Stakes
|
First stakes level. |
required |
b
|
Stakes
|
Second stakes level. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Integer indicating relative stakes. |
Source code in src/synthorg/core/task_enums.py
is_high_stakes
¶
Whether stakes is at or above HIGH.
High/critical work must not proceed on a marginal fit: the assignment and solo-selection paths reject a below-confidence match at this level rather than routing it with a warning.
Returns:
| Type | Description |
|---|---|
bool
|
|
Source code in src/synthorg/core/task_enums.py
Project Enums¶
project_enums
¶
Project-family enumerations.
ProjectStatus
¶
Bases: StrEnum
Lifecycle status of a project.
ACTIVE covers the window where the plan's items are being built.
INTEGRATING and EVALUATING mirror the plan's tail stages so the
cockpit distinguishes an initiative that is still building from one whose
pieces are being assembled, and from one being scored against its
objective: showing all three as ACTIVE would hide the difference between
work in flight and work awaiting a verdict.
GitBackendType
¶
Bases: StrEnum
Discriminator selecting how a project's git repository is stored.
EMBEDDED is the safe default: the product self-hosts a bare repo
on the persistent volume, with no external dependency. LOCAL_PATH
targets a caller-supplied repository on disk. EXTERNAL_REMOTE
delegates to an external forge remote resolved via the connection
catalogue.
EnvironmentType
¶
Bases: StrEnum
Discriminator selecting how a project declares its dev environment.
MANIFEST is the safe default: a backend-agnostic bootstrap manifest
(committed lockfiles plus ordered setup commands) that provisions into
the mounted workspace and runs in both the subprocess and Docker
sandboxes, and emits a stock bootstrap.sh so a fresh clone is
reproducible without the product present. DEVCONTAINER builds a
sealed Docker image from .devcontainer/devcontainer.json (Docker
backend only). NIX provisions a hermetic environment from a
flake.nix via nix develop.
Autonomy Enums¶
autonomy_enums
¶
Autonomy levels and autonomy comparison.
AutonomyLevel
¶
Bases: StrEnum
Autonomy level controlling approval routing for agents.
Determines which actions an agent can execute autonomously vs.
which require human or security-agent approval (see
docs/design/security.md).
compare_autonomy
¶
Compare two autonomy levels.
Returns negative if a is more restrictive than b, zero if equal, positive if a is less restrictive than b.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
AutonomyLevel
|
First autonomy level. |
required |
b
|
AutonomyLevel
|
Second autonomy level. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Integer indicating relative autonomy. |
Source code in src/synthorg/core/autonomy_enums.py
step_down_autonomy
¶
Return the next-more-restrictive autonomy level (one step down).
LOCKED is the floor: stepping down from LOCKED returns LOCKED.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
level
|
AutonomyLevel
|
The current autonomy level. |
required |
Returns:
| Type | Description |
|---|---|
AutonomyLevel
|
The autonomy level one rank more restrictive, or LOCKED when |
AutonomyLevel
|
already at the floor. |
Source code in src/synthorg/core/autonomy_enums.py
Tool Constraints¶
tool_constraints
¶
Sub-constraint models for granular tool access control.
Defines per-dimension constraint enums and a ToolSubConstraints
model that captures file system scope, network mode, git access,
code execution isolation, and terminal access. Each
ToolAccessLevel maps to a default set of sub-constraints
matching the design spec (operations.md, section 11.2).
get_sub_constraints resolves the effective constraints for an
access level, optionally overriding with per-agent custom constraints.
Lives in core (the foundation layer) so leaf domain models such as
core.agent.AgentIdentity can reference ToolSubConstraints without
importing the tools package, whose __init__ eagerly pulls the
provider/engine stack and would re-introduce a cold-import cycle.
ToolAccessLevel
¶
Bases: StrEnum
Access level for tool permissions.
Determines which tool categories an agent can use.
Levels SANDBOXED through ELEVATED form a hierarchy
where each includes all categories from lower levels.
CUSTOM uses only explicit allow/deny lists, ignoring
the hierarchy.
The concrete category sets for each level are defined in
ToolPermissionChecker._LEVEL_CATEGORIES.
FileSystemScope
¶
Bases: StrEnum
File system access scope.
Attributes:
| Name | Type | Description |
|---|---|---|
WORKSPACE_ONLY |
Restrict to the agent's workspace directory. |
|
PROJECT_DIRECTORY |
Access within the project directory tree. |
|
FULL |
Unrestricted file system access. |
NetworkMode
¶
Bases: StrEnum
Network access mode.
Attributes:
| Name | Type | Description |
|---|---|---|
NONE |
No network access permitted. |
|
ALLOWLIST_ONLY |
Only configured host:port pairs allowed. |
|
OPEN |
Unrestricted outbound network access. |
GitAccess
¶
Bases: StrEnum
Git access level.
Attributes:
| Name | Type | Description |
|---|---|---|
LOCAL_ONLY |
Git operations only within the workspace. |
|
READ_AND_BRANCH |
Read operations plus branch creation (no push). |
|
FULL |
All git operations including push. |
CodeExecutionIsolation
¶
Bases: StrEnum
Code execution isolation level.
Attributes:
| Name | Type | Description |
|---|---|---|
CONTAINERIZED |
Run in a container (Docker/K8s sandbox). |
|
PROCESS |
Run as a sandboxed subprocess (lighter isolation). |
TerminalAccess
¶
Bases: StrEnum
Terminal command access level.
Attributes:
| Name | Type | Description |
|---|---|---|
NONE |
No terminal access. |
|
RESTRICTED_COMMANDS |
Only allow/blocklist-filtered commands. |
|
FULL |
Unrestricted command execution. |
ToolSubConstraints
pydantic-model
¶
Bases: BaseModel
Per-level sub-constraints for tool access control.
Each dimension restricts a specific aspect of tool behavior.
The requires_approval tuple lists action type prefixes that
require human approval before execution.
Attributes:
| Name | Type | Description |
|---|---|---|
file_system |
FileSystemScope
|
File system access scope. |
network |
NetworkMode
|
Network access mode. |
git |
GitAccess
|
Git access level. |
code_execution |
CodeExecutionIsolation
|
Code execution isolation level. |
terminal |
TerminalAccess
|
Terminal command access level. |
requires_approval |
tuple[NotBlankStr, ...]
|
Action type prefixes requiring approval. |
network_allowlist |
tuple[NotBlankStr, ...]
|
Allowed host:port pairs when network
mode is |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
file_system(FileSystemScope) -
network(NetworkMode) -
git(GitAccess) -
code_execution(CodeExecutionIsolation) -
terminal(TerminalAccess) -
requires_approval(tuple[NotBlankStr, ...]) -
network_allowlist(tuple[NotBlankStr, ...])
file_system
pydantic-field
¶
file_system = FileSystemScope.PROJECT_DIRECTORY
File system access scope
code_execution
pydantic-field
¶
code_execution = CodeExecutionIsolation.CONTAINERIZED
Code execution isolation level
terminal
pydantic-field
¶
terminal = TerminalAccess.RESTRICTED_COMMANDS
Terminal command access level
requires_approval
pydantic-field
¶
Action type prefixes requiring human approval
network_allowlist
pydantic-field
¶
Allowed host:port pairs for allowlist_only network mode
get_sub_constraints
¶
Resolve effective sub-constraints for an access level.
For CUSTOM access level, custom_constraints is required.
For built-in levels, returns the spec-defined defaults unless
custom_constraints overrides them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
access_level
|
ToolAccessLevel
|
The agent's tool access level. |
required |
custom_constraints
|
ToolSubConstraints | None
|
Optional per-agent overrides. For
|
None
|
Returns:
| Type | Description |
|---|---|
ToolSubConstraints
|
The resolved |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/synthorg/core/tool_constraints.py
Memory Enums¶
memory_enums
¶
Memory persistence and category enumerations.
Core-local leaf: synthorg.core.agent (a cold-import leaf) imports
MemoryLevel and MemoryCategory, and core may not import the
heavy synthorg.memory hub, so these two live here rather than in
synthorg.memory.enums.
MemoryLevel
¶
Bases: StrEnum
Memory persistence level for an agent (§7.3).
MemoryCategory
¶
Bases: StrEnum
Memory type categories for agent memory (§7.2).
PROJECT_DOC is a project-scoped (not agent-scoped) category used
by the living-documentation engine: entries stored under a system docs
agent_id, scoped via the project:<id> tag, surfaced via
ProjectAwareMemoryFacade. KNOWLEDGE is the corpus-scoped
knowledge + provenance substrate (ingested external sources, scoped
via tags, carrying provenance). PROJECT_BRAIN is the project-scoped
structured-state store: brain entries under a system brain agent_id,
scoped via project:<id>, surfaced via the same facade.
Completion Enums¶
completion_enums
¶
Provider-agnostic completion-outcome vocabulary.
FinishReason describes why a model stopped generating. It is shared
vocabulary consumed across the engine, execution-trace, budget, and provider
layers, so it lives in a dependency-free core leaf rather than the heavy
providers hub: a foundation leaf any consumer can import at module level
without dragging the provider package (whose eager init otherwise re-enters
budget.cost_record mid-initialisation).
REASONING_UNSET
module-attribute
¶
Wire value meaning "request no reasoning effort at all".
ReasoningEffort has no member for it because the absence of a request is
not a depth: the parameter is simply omitted, so the model runs at whatever
its provider does by default. Settings that carry a reasoning depth offer
this alongside the real tiers, and every reader maps it back to None.
REASONING_EFFORT_ORDER
module-attribute
¶
REASONING_EFFORT_ORDER = (
ReasoningEffort.MINIMAL,
ReasoningEffort.LOW,
ReasoningEffort.MEDIUM,
ReasoningEffort.HIGH,
)
Cheapest-to-most-thorough order backing :func:reasoning_effort_rank.
FinishReason
¶
Bases: StrEnum
Reason the model stopped generating tokens.
ReasoningEffort
¶
Bases: StrEnum
Provider-agnostic depth of extended reasoning ("thinking") to request.
Maps 1:1 to LiteLLM's reasoning_effort request parameter, which each
provider translates to its own dial (a thinking-token budget on one
provider family, a reasoning-effort tier on another). The values are
ordered from cheapest / shallowest to most thorough. A request only carries
this when the target model advertises reasoning support; otherwise it is
dropped so a non-reasoning model never receives an unsupported parameter.
StrEnum members compare lexicographically, which does NOT match the
intended cheapest-to-most-thorough order, so any ordinal comparison must go
through :func:reasoning_effort_rank, never < / > on the members.
reasoning_effort_rank
¶
Return the ordinal rank of effort (0 = cheapest, higher = deeper).
Use for ordering comparisons instead of < / > on the enum, whose
StrEnum members compare lexicographically (which mis-orders the tiers).
Returns:
| Type | Description |
|---|---|
int
|
The 0-based rank of effort in the cheapest-to-most-thorough order. |
Source code in src/synthorg/core/completion_enums.py
Agent¶
agent
¶
Agent identity and configuration models.
PersonalityConfig
pydantic-model
¶
Bases: BaseModel
Personality traits and communication style for an agent.
Big Five (OCEAN) floats (0.0-1.0) are internal scoring dimensions used for compatibility calculations. Behavioral enums produce natural-language labels injected into system prompts that LLMs respond to effectively.
Attributes:
| Name | Type | Description |
|---|---|---|
traits |
tuple[NotBlankStr, ...]
|
Personality trait keywords. |
communication_style |
NotBlankStr
|
Free-text style description. |
risk_tolerance |
RiskTolerance
|
Risk tolerance level. |
creativity |
CreativityLevel
|
Creativity level. |
description |
str
|
Extended personality description. |
openness |
float
|
Big Five openness (curiosity, creativity). 0.0-1.0. |
conscientiousness |
float
|
Big Five conscientiousness (thoroughness). 0.0-1.0. |
extraversion |
float
|
Big Five extraversion (assertiveness). 0.0-1.0. |
agreeableness |
float
|
Big Five agreeableness (cooperation). 0.0-1.0. |
stress_response |
float
|
Emotional stability (1.0 = very calm). 0.0-1.0. |
decision_making |
DecisionMakingStyle
|
Decision-making approach. |
collaboration |
CollaborationPreference
|
Preferred collaboration mode. |
verbosity |
CommunicationVerbosity
|
Communication verbosity level. |
conflict_approach |
ConflictApproach
|
Conflict resolution approach. |
Config:
frozen:Trueextra:forbidallow_inf_nan:False
Fields:
-
traits(tuple[NotBlankStr, ...]) -
communication_style(NotBlankStr) -
risk_tolerance(RiskTolerance) -
creativity(CreativityLevel) -
description(str) -
openness(float) -
conscientiousness(float) -
extraversion(float) -
agreeableness(float) -
stress_response(float) -
decision_making(DecisionMakingStyle) -
collaboration(CollaborationPreference) -
verbosity(CommunicationVerbosity) -
conflict_approach(ConflictApproach)
communication_style
pydantic-field
¶
Communication style description
conscientiousness
pydantic-field
¶
Big Five conscientiousness (thoroughness, reliability)
decision_making
pydantic-field
¶
decision_making = DecisionMakingStyle.CONSULTATIVE
Decision-making approach
collaboration
pydantic-field
¶
collaboration = CollaborationPreference.TEAM
Preferred collaboration mode
verbosity
pydantic-field
¶
verbosity = CommunicationVerbosity.BALANCED
Communication verbosity level
conflict_approach
pydantic-field
¶
conflict_approach = ConflictApproach.COLLABORATE
Conflict resolution approach
SkillSet
pydantic-model
¶
ModelConfig
pydantic-model
¶
Bases: BaseModel
LLM model configuration for an agent.
An agent binds exactly one (provider, model) pair, and there is no
spare. A bare fallback model id would name a model with no connection
behind it, which is the ambiguity explicit provider binding exists to
remove; and an agent whose pair is unserviceable is an employee who is
out, so the org's answer is another agent rather than another model
behind this one's name.
Attributes:
| Name | Type | Description |
|---|---|---|
provider |
NotBlankStr
|
LLM provider name (e.g. |
model_id |
NotBlankStr
|
Model identifier (e.g. |
temperature |
float
|
Sampling temperature (0.0 to 2.0). |
max_tokens |
int | None
|
Output ceiling for ONE response, or |
capability |
CapabilityLevel | None
|
What the model can be trusted with
( |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
provider(NotBlankStr) -
model_id(NotBlankStr) -
temperature(float) -
max_tokens(int | None) -
capability(CapabilityLevel | None)
Validators:
-
_reject_capability_literal_as_model→model_id
AgentRetentionRule
pydantic-model
¶
Bases: BaseModel
Per-category retention override for an agent.
Structurally identical to
:class:~synthorg.memory.consolidation.models.RetentionRule but
defined in core to avoid a core -> memory import dependency.
Attributes:
| Name | Type | Description |
|---|---|---|
category |
MemoryCategory
|
Memory category this override applies to. |
retention_days |
int
|
Number of days to retain memories in this category. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
category(MemoryCategory) -
retention_days(int)
MemoryConfig
pydantic-model
¶
Bases: BaseModel
Memory configuration for an agent.
Attributes:
| Name | Type | Description |
|---|---|---|
type |
MemoryLevel
|
Memory persistence type. |
retention_days |
int | None
|
Days to retain memories ( |
retention_overrides |
tuple[AgentRetentionRule, ...]
|
Per-category retention overrides for this agent. These take priority over company-level per-category rules during retention enforcement. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
type(MemoryLevel) -
retention_days(int | None) -
retention_overrides(tuple[AgentRetentionRule, ...])
Validators:
-
_validate_retention_consistency -
_validate_unique_override_categories
retention_overrides
pydantic-field
¶
Per-category retention overrides for this agent
ToolPermissions
pydantic-model
¶
Bases: BaseModel
Tool access permissions for an agent.
Attributes:
| Name | Type | Description |
|---|---|---|
access_level |
ToolAccessLevel
|
Tool access level controlling which categories are available. |
allowed |
tuple[NotBlankStr, ...]
|
Explicitly allowed tool names. |
denied |
tuple[NotBlankStr, ...]
|
Explicitly denied tool names. |
mcp_capabilities |
tuple[NotBlankStr, ...]
|
MCP capability patterns controlling which
internal MCP tools the agent can see. Supports wildcards
(e.g. |
sub_constraints |
ToolSubConstraints | None
|
Optional per-agent sub-constraints overriding
the access level defaults. When |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
access_level(ToolAccessLevel) -
allowed(tuple[NotBlankStr, ...]) -
denied(tuple[NotBlankStr, ...]) -
mcp_capabilities(tuple[NotBlankStr, ...]) -
sub_constraints(ToolSubConstraints | None)
Validators:
-
_validate_no_overlap -
_validate_mcp_capability_format
mcp_capabilities
pydantic-field
¶
MCP capability patterns (e.g. 'tasks:read', 'agents:*')
AgentIdentity
pydantic-model
¶
Bases: BaseModel
Complete agent identity card.
Every agent in the company is represented by an AgentIdentity
containing its role, personality, model backend, memory settings,
tool permissions, and authority configuration.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
UUID
|
Unique agent identifier. |
name |
PersonaLabelStr
|
Agent display name. |
role |
PersonaLabelStr
|
Role name (string reference to :class: |
department |
PersonaLabelStr
|
Department name (string reference). |
personality |
PersonalityConfig
|
Personality configuration. |
skills |
SkillSet
|
Primary and secondary skill set. |
model |
ModelConfig
|
LLM model configuration. |
memory |
MemoryConfig
|
Memory configuration. |
tools |
ToolPermissions
|
Tool permissions. |
authority |
Authority
|
Authority configuration for this agent. |
autonomy_level |
AutonomyLevel | None
|
Per-agent autonomy level override ( |
strategic_output_mode |
StrategicOutputMode | None
|
Per-agent strategic output mode override
( |
hiring_date |
date
|
Date the agent was hired. |
status |
AgentStatus
|
Current lifecycle status. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(UUID) -
name(PersonaLabelStr) -
role(PersonaLabelStr) -
department(PersonaLabelStr) -
personality(PersonalityConfig) -
skills(SkillSet) -
model(ModelConfig) -
memory(MemoryConfig) -
tools(ToolPermissions) -
authority(Authority) -
autonomy_level(AutonomyLevel | None) -
strategic_output_mode(StrategicOutputMode | None) -
hiring_date(date) -
status(AgentStatus)
strategic_output_mode
pydantic-field
¶
Per-agent strategic output mode override. None inherits the company strategy config default.
Company¶
company
¶
Company structure and configuration models.
Department-internal structure models live in
:mod:synthorg.core.company_departments; cross-department handoff and
escalation models live in :mod:synthorg.core.company_handoffs.
CompanyConfig
pydantic-model
¶
Bases: BaseModel
Company-wide configuration settings.
Attributes:
| Name | Type | Description |
|---|---|---|
autonomy |
AutonomyConfig
|
Autonomy configuration (level + presets). |
approval_timeout |
ApprovalTimeoutConfig
|
Timeout policy for pending approval items. |
budget_monthly |
float
|
Setup-time monthly budget seed only; the enforced
value is settings |
communication_pattern |
NotBlankStr
|
Default communication pattern name. |
tool_access_default |
tuple[NotBlankStr, ...]
|
Default tool access for all agents. |
middleware |
MiddlewareConfig
|
Agent and coordination middleware configuration. |
session_replay_on_start |
bool
|
When |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
autonomy(AutonomyConfig) -
approval_timeout(ApprovalTimeoutConfig) -
budget_monthly(float) -
communication_pattern(NotBlankStr) -
tool_access_default(tuple[NotBlankStr, ...]) -
middleware(MiddlewareConfig) -
session_replay_on_start(bool)
budget_monthly
pydantic-field
¶
Setup-time monthly budget seed in the configured currency. The enforced value is settings budget.total_monthly (the single source of truth); this field is not read at runtime.
communication_pattern
pydantic-field
¶
Default communication pattern
session_replay_on_start
pydantic-field
¶
Replay session from event log on agent start
HRRegistry
pydantic-model
¶
Bases: BaseModel
Human resources registry for the company.
available_roles and hiring_queue intentionally allow duplicate
entries to represent multiple openings for the same role or position.
Attributes:
| Name | Type | Description |
|---|---|---|
active_agents |
tuple[NotBlankStr, ...]
|
Currently active agent names (must be unique). |
available_roles |
tuple[NotBlankStr, ...]
|
Roles available for hiring (duplicates allowed). |
hiring_queue |
tuple[NotBlankStr, ...]
|
Roles in the hiring pipeline (duplicates allowed). |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
active_agents(tuple[NotBlankStr, ...]) -
available_roles(tuple[NotBlankStr, ...]) -
hiring_queue(tuple[NotBlankStr, ...])
Validators:
-
_validate_no_duplicate_active_agents
Company
pydantic-model
¶
Bases: BaseModel
Top-level company entity.
Validates that department names are unique and that budget allocations do not exceed 100%. The sum may be less than 100% to allow for an unallocated reserve.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
UUID
|
Company identifier. |
name |
NotBlankStr
|
Company name. |
type |
CompanyType
|
Company template type. |
departments |
tuple[Department, ...]
|
Company departments. |
config |
CompanyConfig
|
Company-wide configuration. |
hr_registry |
HRRegistry
|
HR registry. |
workflow_handoffs |
tuple[WorkflowHandoff, ...]
|
Cross-department workflow handoffs. |
escalation_paths |
tuple[EscalationPath, ...]
|
Cross-department escalation paths. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(UUID) -
name(NotBlankStr) -
type(CompanyType) -
departments(tuple[Department, ...]) -
config(CompanyConfig) -
hr_registry(HRRegistry) -
workflow_handoffs(tuple[WorkflowHandoff, ...]) -
escalation_paths(tuple[EscalationPath, ...])
Validators:
-
_validate_departments
Role¶
role
¶
Role and skill domain models.
Skill
pydantic-model
¶
Bases: BaseModel
Structured capability description, A2A AgentSkill-aligned.
Mirrors the A2A protocol AgentSkill shape so projection to
A2AAgentSkill is lossless. proficiency is the SynthOrg-specific
addition used for quality-aware routing ("route to the agent with the
highest Python proficiency").
Attributes:
| Name | Type | Description |
|---|---|---|
id |
NotBlankStr
|
Unique skill identifier (e.g. |
name |
NotBlankStr
|
Human-readable display name (e.g. |
description |
str
|
Capability description for semantic matching. |
tags |
tuple[NotBlankStr, ...]
|
Searchable tags for multi-faceted routing. |
input_modes |
tuple[NotBlankStr, ...]
|
MIME types the agent accepts for this skill. |
output_modes |
tuple[NotBlankStr, ...]
|
MIME types the agent produces for this skill. |
proficiency |
float
|
Proficiency level in |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(NotBlankStr) -
name(NotBlankStr) -
description(str) -
tags(tuple[NotBlankStr, ...]) -
input_modes(tuple[NotBlankStr, ...]) -
output_modes(tuple[NotBlankStr, ...]) -
proficiency(float)
Validators:
-
_reject_duplicate_entries→tags,input_modes,output_modes
Authority
pydantic-model
¶
Bases: BaseModel
Authority scope for an agent or role.
Attributes:
| Name | Type | Description |
|---|---|---|
can_approve |
tuple[NotBlankStr, ...]
|
Task types this role can approve. |
reports_to |
NotBlankStr | None
|
Role this position reports to. |
can_delegate_to |
tuple[NotBlankStr, ...]
|
Roles this position can delegate tasks to. |
budget_limit |
float
|
Maximum spend per task in base currency units. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
can_approve(tuple[NotBlankStr, ...]) -
reports_to(NotBlankStr | None) -
can_delegate_to(tuple[NotBlankStr, ...]) -
budget_limit(float)
Role
pydantic-model
¶
Bases: BaseModel
A job definition within the organization.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
NotBlankStr
|
Role name (e.g. |
department |
DepartmentName
|
Department this role belongs to. |
required_skills |
tuple[NotBlankStr, ...]
|
Skills required for this role. |
reports_to |
NotBlankStr | None
|
Name of the role this position reports to, or
|
tool_access |
tuple[NotBlankStr, ...]
|
Tools available to this role. |
system_prompt_template |
NotBlankStr | None
|
Template file for system prompt. |
description |
str
|
Human-readable description. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
name(NotBlankStr) -
department(DepartmentName) -
required_skills(tuple[NotBlankStr, ...]) -
reports_to(NotBlankStr | None) -
tool_access(tuple[NotBlankStr, ...]) -
system_prompt_template(NotBlankStr | None) -
description(str)
CustomRole
pydantic-model
¶
Bases: BaseModel
User-defined custom role via configuration.
Unlike :class:Role, the department field accepts arbitrary strings
in addition to :class:~synthorg.organization.enums.DepartmentName values,
allowing users to define roles in non-standard departments.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
NotBlankStr
|
Custom role name. |
department |
DepartmentName | str
|
Department (standard or custom name). |
required_skills |
tuple[NotBlankStr, ...]
|
Required skills for this role. |
system_prompt_template |
NotBlankStr | None
|
Template file for system prompt. |
reports_to |
NotBlankStr | None
|
Name of the role this position reports to, or
|
suggested_model |
NotBlankStr | None
|
Suggested model capability rung. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
name(NotBlankStr) -
department(DepartmentName | str) -
required_skills(tuple[NotBlankStr, ...]) -
system_prompt_template(NotBlankStr | None) -
reports_to(NotBlankStr | None) -
suggested_model(NotBlankStr | None)
Validators:
-
_department_not_empty→department
Role Catalog¶
role_catalog
¶
Built-in role catalog and the reporting graph.
Provides the canonical set of built-in roles from the Agents design page
(Role Catalog). Authority follows each role's reports_to edge up to
the CEO (the single root); see :mod:synthorg.core.authority for the
graph queries built on top of this catalog.
RED_TEAM_ROLE_NAME
module-attribute
¶
Canonical name of the built-in Red Team role.
Exposed so other modules (the red-team subsystem, tests) reference a single string constant instead of duplicating the literal.
COMPLETION_REVIEWER_ROLE_NAME
module-attribute
¶
Canonical name of the built-in Completion Reviewer role.
Exposed so the completion-oracle subsystem references a single string constant instead of duplicating the literal.
KNOWLEDGE_ARCHITECT_ROLE_NAME
module-attribute
¶
Canonical name of the built-in Knowledge Architect role.
Exposed so the org-memory write tools tag their author with a single string constant instead of duplicating the literal.
GATE_ROLE_NAMES
module-attribute
¶
GATE_ROLE_NAMES = frozenset(
{
normalize_identifier(RED_TEAM_ROLE_NAME),
normalize_identifier(COMPLETION_REVIEWER_ROLE_NAME),
}
)
Normalised names of the roles that judge work rather than perform it.
get_builtin_role
¶
Look up a built-in role by name (case-insensitive, whitespace-stripped).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Role name to search for. |
required |
Returns:
| Type | Description |
|---|---|
Role | None
|
The matching Role, or |
Source code in src/synthorg/core/role_catalog.py
role_is_gate_role
¶
Report whether role is one the completion gates select a judge from.
Holding one confers judging authority over other agents' work, so the answer decides where the org treats the role as special: HR keeps at most one hire in flight per gate role (two sweeps must not open two approval items for the one role), the registry notifies the review-staffing sweep when a holder appears, and the agent MCP surface refuses to grant one at all. None of these is a confinement: an agent is confined to an initiative by its workspace and its tool governance, never by its role.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
role
|
str
|
The role name to test, in whatever form an operator typed it. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Source code in src/synthorg/core/role_catalog.py
Task¶
task
¶
Task domain model and acceptance criteria.
AcceptanceCriterion
pydantic-model
¶
Bases: BaseModel
A single acceptance criterion for a task.
Attributes:
| Name | Type | Description |
|---|---|---|
description |
NotBlankStr
|
The criterion text. |
met |
bool
|
Whether this criterion has been satisfied. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
description(NotBlankStr) -
met(bool)
Task
pydantic-model
¶
Bases: BaseModel
A unit of work within the company.
Represents a task from creation through completion, with full lifecycle tracking, dependency modeling, and acceptance criteria. Field schema matches the Engine design page.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
UUID
|
Unique task identifier (auto-generated UUID). |
title |
NotBlankStr
|
Short task title. |
description |
NotBlankStr
|
Detailed task description. |
type |
TaskType
|
Classification of the task's work type. |
priority |
Priority
|
Task urgency and importance level. |
project |
NotBlankStr
|
Project ID this task belongs to. |
plan_id |
UUID | None
|
Plan whose dispatch created this task ( |
plan_item_id |
UUID | None
|
Plan item this task implements ( |
created_by |
NotBlankStr
|
Agent name of the task creator. |
requested_by_user_id |
NotBlankStr | None
|
User id of the human who filed the task via
the API ( |
assigned_to |
NotBlankStr | None
|
Agent ID of the assignee ( |
reviewers |
tuple[NotBlankStr, ...]
|
Agent IDs of designated reviewers. |
dependencies |
tuple[NotBlankStr, ...]
|
IDs of tasks this task depends on. |
artifacts_expected |
tuple[ExpectedArtifact, ...]
|
Artifacts expected to be produced. |
acceptance_criteria |
tuple[AcceptanceCriterion, ...]
|
Structured acceptance criteria. |
estimated_complexity |
Complexity
|
Task complexity estimate. |
budget_limit |
float
|
Maximum spend for this task in the configured currency. |
deadline |
str | None
|
Optional deadline (ISO 8601 string or |
max_retries |
int
|
Max reassignment attempts after failure (default 1). |
status |
TaskStatus
|
Current lifecycle status. |
parent_task_id |
NotBlankStr | None
|
Parent task ID when created via delegation
( |
delegation_chain |
tuple[NotBlankStr, ...]
|
Ordered agent names of delegators (root first). |
task_structure |
TaskStructure | None
|
Classification of how subtasks relate to each
other ( |
coordination_topology |
CoordinationTopology
|
Coordination topology for multi-agent
execution (defaults to |
middleware_override |
tuple[NotBlankStr, ...] | None
|
Per-task middleware chain override
( |
metadata |
dict[str, object]
|
Arbitrary key-value metadata for pipeline tracking, labels, and operator-defined context. Deep-copied at construction to prevent external mutation. |
created_at |
AwareDatetime
|
When the task was filed (tz-aware UTC). Load-bearing rather than audit decoration: it is the only durable answer to "how long has this been running", which the duration histogram measures, the cockpit's stuck heuristic compares against a cutoff, and an operator needs for a row nothing has driven since a restart. An in-process map cannot answer any of the three, because a restart is exactly when the question gets asked. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(UUID) -
title(NotBlankStr) -
description(NotBlankStr) -
type(TaskType) -
priority(Priority) -
project(NotBlankStr) -
blocked_reason(BlockedReason | None) -
plan_id(UUID | None) -
plan_item_id(UUID | None) -
created_by(NotBlankStr) -
requested_by_user_id(NotBlankStr | None) -
assigned_to(NotBlankStr | None) -
reviewers(tuple[NotBlankStr, ...]) -
dependencies(tuple[NotBlankStr, ...]) -
artifacts_expected(tuple[ExpectedArtifact, ...]) -
acceptance_criteria(tuple[AcceptanceCriterion, ...]) -
estimated_complexity(Complexity) -
stakes(Stakes) -
budget_limit(float) -
deadline(str | None) -
max_retries(int) -
status(TaskStatus) -
parent_task_id(NotBlankStr | None) -
delegation_chain(tuple[NotBlankStr, ...]) -
task_structure(TaskStructure | None) -
coordination_topology(CoordinationTopology) -
source(TaskSource | None) -
middleware_override(tuple[NotBlankStr, ...] | None) -
metadata(dict[str, object]) -
hard_ceiling(float | None) -
hard_token_ceiling(int | None) -
forecast_id(UUID | None) -
created_at(AwareDatetime)
Validators:
-
_deepcopy_metadata -
_validate_deadline_format -
_validate_invariants
blocked_reason
pydantic-field
¶
Why the task is parked at BLOCKED, when the writer named it. BLOCKED is reached for unrelated reasons, so a rule written for one of them reads this rather than the status.
requested_by_user_id
pydantic-field
¶
User id of the human who filed this task via the API (distinct from created_by, which is the agent name). Drives SSE event-stream session ownership: only the requester (or a CEO) may subscribe to a session keyed by this task's id. None for agent-internal tasks.
estimated_complexity
pydantic-field
¶
estimated_complexity = Complexity.MEDIUM
Task complexity estimate
stakes
pydantic-field
¶
stakes = Stakes.NORMAL
How consequential this task is: the minimum capability rung selection asks for (a weaker agent may still take it below the park floor, with the concession logged), and the value compared against the configured red-team threshold
budget_limit
pydantic-field
¶
Maximum spend for this task in the configured currency
delegation_chain
pydantic-field
¶
Ordered agent names of delegators (root first)
task_structure
pydantic-field
¶
Classification of subtask relationships (None = not classified)
coordination_topology
pydantic-field
¶
coordination_topology = CoordinationTopology.AUTO
Coordination topology for multi-agent execution
middleware_override
pydantic-field
¶
Per-task middleware chain override (None = use company default)
hard_ceiling
pydantic-field
¶
Per-run hard real-money ceiling in the configured currency. When the in-loop BudgetChecker observes accumulated_cost >= hard_ceiling it raises RunHardCeilingExceededError and the engine parks the context via ApprovalGate so the operator can raise the ceiling and resume. None falls back to the global budget.run_hard_ceiling setting.
hard_token_ceiling
pydantic-field
¶
Per-run hard token ceiling. The money ceiling above is only a bound where the provider bills per token: against a flat-rate subscription cost never rises, so it can never fire and the run's only remaining bound is its turn budget. Tokens are measured on every provider, so this is the same backstop in the unit that is always available. When the in-loop BudgetChecker observes accumulated tokens >= hard_token_ceiling it raises RunHardTokenCeilingExceededError and the engine parks the context, so the operator raises the ceiling and resumes with the workspace intact. None falls back to the global budget.run_hard_token_ceiling setting.
forecast_id
pydantic-field
¶
Identifier of the pre-flight cost Forecast row this task was dispatched against. The work-entry adapter sets this after the operator approves the forecast; the engine plumbs it onto the parked-context payload when a ceiling halt occurs so the resume UI can show the original estimate alongside the accumulated cost.
with_transition
¶
Create a new Task with a validated status transition.
Calls :func:~synthorg.core.task_transitions.validate_transition
before producing the new instance, ensuring the state machine is
enforced. Uses model_validate so all validators run on the
new instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
TaskStatus
|
The desired target status. |
required |
**overrides
|
object
|
Additional field overrides for the new task. |
{}
|
Returns:
| Type | Description |
|---|---|
Task
|
A new Task with the target status. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the transition is not valid or overrides
contain |
Source code in src/synthorg/core/task.py
Task Transitions¶
task_transitions
¶
Task lifecycle state machine transitions.
Defines the valid state transitions for the task lifecycle, based on the Engine design page, extended with BLOCKED, CANCELLED, FAILED, INTERRUPTED, SUSPENDED, REJECTED, AUTH_REQUIRED, and AWAITING_INPUT transitions for completeness::
CREATED -> ASSIGNED | REJECTED | FAILED
ASSIGNED -> IN_PROGRESS | AUTH_REQUIRED | BLOCKED | CANCELLED
| FAILED | INTERRUPTED | SUSPENDED
IN_PROGRESS -> IN_REVIEW | AWAITING_INPUT | AUTH_REQUIRED | BLOCKED
| CANCELLED | FAILED | INTERRUPTED | SUSPENDED
IN_REVIEW -> COMPLETED | IN_PROGRESS (rework) | BLOCKED | CANCELLED
AUTH_REQUIRED -> ASSIGNED (approved) | CANCELLED (denied/timeout)
AWAITING_INPUT -> IN_PROGRESS (answer received) | CANCELLED
BLOCKED -> ASSIGNED (unblocked) | IN_REVIEW (an escalated review's
answer rejoins it) | CANCELLED (abandoned)
FAILED -> ASSIGNED (reassignment for retry) | CANCELLED (abandoned)
INTERRUPTED -> ASSIGNED (reassignment on restart) | CANCELLED (abandoned)
SUSPENDED -> ASSIGNED (resume from checkpoint) | CANCELLED (abandoned)
COMPLETED, CANCELLED, and REJECTED are terminal states with no outgoing transitions. FAILED, INTERRUPTED, and SUSPENDED are non-terminal (can be reassigned). AUTH_REQUIRED (waiting for authorization) and AWAITING_INPUT (paused for a human's answer to a mid-task clarification) are non-terminal.
Every stuck state carries a direct CANCELLED exit because
reassignment is not one: ASSIGNED requires an assignee, and a task
that failed before it was ever assigned has none, so routing its
abandonment through ASSIGNED failed the Task validator and left
the row with no reachable exit at all. Its project then could not be
deleted by any route, because the cascade could not resolve it.
validate_transition
¶
Validate that a state transition is allowed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
current
|
TaskStatus
|
The current task status. |
required |
target
|
TaskStatus
|
The desired target status. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the transition from current to target
is not in :data: |
Source code in src/synthorg/core/task_transitions.py
transition_path
¶
Return the shortest valid hop sequence from current to target.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
current
|
TaskStatus
|
The current task status. |
required |
target
|
TaskStatus
|
The desired task status. |
required |
Returns:
| Type | Description |
|---|---|
tuple[TaskStatus, ...] | None
|
|
tuple[TaskStatus, ...] | None
|
statuses ending in target (each hop individually valid) when |
tuple[TaskStatus, ...] | None
|
a lifecycle path exists; or |
tuple[TaskStatus, ...] | None
|
unreachable from current (e.g. current is terminal). |
Source code in src/synthorg/core/task_transitions.py
Project¶
project
¶
Project domain model for task collection management.
Project
pydantic-model
¶
Bases: BaseModel
A collection of related tasks with a shared goal, lead, and deadline.
Projects organize tasks into a coherent unit of work with budget tracking. Per the Design Overview glossary and entity relationship tree.
The project stores no roster of its own. Who worked an initiative is
derived: the assignees of its tasks that left the queue, plus the
recorded lead, whose leading counts even when it took no task itself
(initiative_contributors). The derivation exists for the same reason
task_ids is not stored: a collection embedded in a row has to be
written by every actor that creates a child, in the same transaction,
forever, and an unwritten one reads as "nobody".
Attributes:
| Name | Type | Description |
|---|---|---|
id |
UUID
|
Unique project identifier (auto-generated UUID). |
name |
NotBlankStr
|
Project display name. |
description |
str
|
Detailed project description. |
lead |
NotBlankStr | None
|
Agent ID of the project lead. |
plan_id |
UUID | None
|
The plan this project is currently executing, or |
deadline |
str | None
|
Optional deadline (ISO 8601 string or |
budget |
float
|
Total budget in base currency (configurable, defaults to EUR). |
status |
ProjectStatus
|
Current project status. |
autonomy_mode |
AutonomyLevel | None
|
Operator-set oversight mode for this initiative. When
set, it becomes the initiative-level autonomy override the gate
resolves against (more specific than a department default, less
than a per-agent override); |
version |
int
|
Optimistic-concurrency revision, bumped on each persisted edit so a version-guarded write cannot silently clobber a concurrent update (e.g. two workers staffing the same lead). |
created_at |
AwareDatetime
|
When the project was opened (tz-aware UTC). Load-bearing beyond the audit trail: intake bounds its reuse of an existing project by age, and without a recorded start there is nothing to measure that age against. |
updated_at |
AwareDatetime
|
Last-revision timestamp (tz-aware UTC). |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(UUID) -
name(NotBlankStr) -
description(str) -
lead(NotBlankStr | None) -
plan_id(UUID | None) -
deadline(str | None) -
budget(float) -
status(ProjectStatus) -
autonomy_mode(AutonomyLevel | None) -
version(int) -
created_at(AwareDatetime) -
updated_at(AwareDatetime)
Validators:
-
_validate_deadline_format
autonomy_mode
pydantic-field
¶
Operator-set oversight mode for this initiative (None inherits the department or company default)
Approval¶
enums
¶
Approval workflow enumerations.
ApprovalStatus
¶
Bases: StrEnum
Status of a human approval item.
ApprovalRiskLevel
¶
Bases: StrEnum
Risk level assigned to an approval item.
QuestionReversibility
¶
Bases: StrEnum
How reversible the choice behind an agent's question is.
Declared by the agent on request_clarification /
request_project_decision and recorded on the resulting
ApprovalItem metadata, so the operator sees at a glance whether an
answer is undoable and the chat surface can rank the questions that are.
It deliberately does not feed ApprovalRiskLevel, which drives autonomy
routing and the approval-timeout policy: escalating a hard-to-reverse
question there would silently re-route parks that exist today.
Attributes:
| Name | Type | Description |
|---|---|---|
REVERSIBLE |
Undoing the choice is a quick edit. |
|
HARD_TO_REVERSE |
Undoing the choice costs real rework. |
ApprovalSource
¶
Bases: StrEnum
Origin of an approval item, fixed at creation.
Routing of a decided approval (mid-execution resume vs. review gate) keys off this persisted discriminator rather than a live parked-context probe, keeping the flow deterministic.
Attributes:
| Name | Type | Description |
|---|---|---|
PARKED_CONTEXT |
Backs a parked agent execution context (SecOps
escalation or |
|
REVIEW_GATE |
Any other approval (autonomy, hiring, promotion, ...); drives the review-gate transition. Default. |
|
CONVERSATIONAL_INTAKE |
A work item proposed via the
conversational interface; approval rebuilds the |
|
CONVERSATIONAL_INVITE |
An agent's request to add another agent to a group conversation; approval adds the participant + hands over the transcript, rejection leaves membership. |
|
PLAN_REVIEW |
A decomposed plan awaiting human approval before a
team builds; approval dispatches the exact approved plan
( |
approval
¶
Human approval item domain model.
Represents an action that requires human approval before proceeding. Used by the approval queue API and referenced by engine and security subsystems.
ApprovalItem
pydantic-model
¶
Bases: BaseModel
A single item in the human approval queue.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
UUID
|
Unique approval identifier. |
action_type |
NotBlankStr
|
What kind of action requires approval. |
title |
NotBlankStr
|
Short summary of the approval request. |
description |
NotBlankStr
|
Detailed explanation. |
requested_by |
NotBlankStr
|
Agent or system that requested approval. |
risk_level |
ApprovalRiskLevel
|
Assessed risk level. |
status |
ApprovalStatus
|
Current approval status. |
created_at |
AwareDatetime
|
When the item was created. |
expires_at |
AwareDatetime | None
|
Optional expiration time for auto-expiry. |
decided_at |
AwareDatetime | None
|
When the decision was made (set on approve/reject). |
decided_by |
NotBlankStr | None
|
Who made the decision (set on approve/reject). |
decision_reason |
NotBlankStr | None
|
Reason for the decision (required on reject). |
task_id |
NotBlankStr | None
|
Optional associated task identifier. |
source |
ApprovalSource
|
Origin discriminator fixed at creation. Routes a
decided approval deterministically (parked-context resume
vs. review gate) without a live parked-context probe.
Defaults to |
consumed_at |
AwareDatetime | None
|
When an APPROVED one-shot grant was spent. |
metadata |
dict[str, str]
|
Additional key-value metadata. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(UUID) -
action_type(NotBlankStr) -
title(NotBlankStr) -
description(NotBlankStr) -
requested_by(NotBlankStr) -
risk_level(ApprovalRiskLevel) -
source(ApprovalSource) -
status(ApprovalStatus) -
created_at(AwareDatetime) -
expires_at(AwareDatetime | None) -
decided_at(AwareDatetime | None) -
decided_by(NotBlankStr | None) -
decision_reason(NotBlankStr | None) -
task_id(NotBlankStr | None) -
consumed_at(AwareDatetime | None) -
evidence_package(EvidencePackage | None) -
metadata(dict[str, str])
Validators:
-
_deep_copy_metadata -
_validate_decision_fields -
_validate_expiry -
_validate_consumption
Effective Autonomy¶
effective_autonomy
¶
Resolved-autonomy value object.
EffectiveAutonomy is the expanded, resolved autonomy an agent runs under,
produced by :class:~synthorg.security.autonomy.resolver.AutonomyResolver. It is
shared vocabulary the engine, workers, tools, and meta layers annotate against, so
it lives in a dependency-free core leaf (it needs only the autonomy-level enum)
rather than the heavy security package, which any consumer would otherwise have
to drag in to reference the type at module level.
EffectiveAutonomy
pydantic-model
¶
Bases: BaseModel
Resolved, expanded autonomy for an agent's execution run.
Produced by :class:~synthorg.security.autonomy.resolver.AutonomyResolver
by resolving the three-level chain (agent, department, company) and
expanding category shortcuts into concrete action types.
Attributes:
| Name | Type | Description |
|---|---|---|
level |
AutonomyLevel
|
Resolved autonomy level. |
auto_approve_actions |
frozenset[str]
|
Concrete action types that are auto-approved. |
human_approval_actions |
frozenset[str]
|
Concrete action types requiring human approval. |
security_agent |
bool
|
Whether the security agent reviews escalations. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
level(AutonomyLevel) -
auto_approve_actions(frozenset[str]) -
human_approval_actions(frozenset[str]) -
security_agent(bool)
Validators:
-
_validate_disjoint
Red-Team Review Input¶
redteam_review_input
¶
Red-team gate input value object.
RedTeamReviewInput is what the adversarial review gate sees on entry: a
deliverable plus the context the gate needs to attack it. It is assembled in the
engine and consumed by the security red-team subsystem, so it lives in a
dependency-free core leaf (it needs only the string and autonomy-level
primitives) rather than the heavy security.redteam package, letting either
side annotate against it at module level without a cross-package cycle.
DeliverableArtifact
pydantic-model
¶
Bases: BaseModel
One file the task declared and the run actually produced.
The same bytes the composed deliverable_content carries, in typed
form. A consumer that needs to judge a produced file on its own (the
house-style backstop, which asks a per-file question and applies a
per-path exemption) cannot get it back out of the composed JSON document
without parsing the thing it was just handed.
Attributes:
| Name | Type | Description |
|---|---|---|
path |
NotBlankStr
|
The declared path, as the task named it. |
content |
str
|
What was read at that path, empty for an empty file and bounded by the reader's own per-file budget. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
path(NotBlankStr) -
content(str)
RedTeamReviewInput
pydantic-model
¶
Bases: BaseModel
What the gate sees on entry: the deliverable plus its context.
The gate's evaluation surface. Lives here (not on Task directly) so the red-team subsystem can be exercised without dragging the full Task model and its dependencies into every test.
Attributes:
| Name | Type | Description |
|---|---|---|
task_id |
NotBlankStr
|
The deliverable's owning task. |
execution_id |
NotBlankStr
|
The execution that produced the deliverable. |
deliverable_content |
NotBlankStr
|
The artifact text the red-team attacks. |
agent_summary |
NotBlankStr
|
The agent's own closing message, carried alongside the artifacts rather than folded into them, so a consumer can ask about the prose the agent wrote without the delivered source files in the same string. |
produced_artifacts |
tuple[DeliverableArtifact, ...]
|
The files the run actually produced, in typed
form. Empty when the task declared none, or when the workspace
could not be consulted; the composed |
acceptance_criteria |
tuple[NotBlankStr, ...]
|
The brief's acceptance criteria, used by the agent prompt; a dedicated requirements-coverage checker (not yet built) would also consume it. |
assigned_agent_id |
NotBlankStr
|
The agent that produced the deliverable (forbidden as red-team reviewer; enforced one layer up by the review-gate's self-review guard). |
autonomy |
AutonomyLevel
|
Effective autonomy level governing severity-tiered
routing in :mod: |
project_id |
NotBlankStr | None
|
Owning project of the deliverable, when known. The
substrate-backed grounding checker scopes its corpus search
to it; |
stakes |
Stakes
|
The reviewed work's stakes, carried so the gate can pick a red-teamer capable enough for it. Capability follows the TASK, never the reviewer's seniority. Required, with no default: these two decide WHICH agent is asked to attack the deliverable, and a caller that omitted them would silently get a mid-tier adversary for work the org classified as critical. |
estimated_complexity |
Complexity
|
The reviewed work's complexity, the second half of that same requirement, required for the same reason. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
task_id(NotBlankStr) -
execution_id(NotBlankStr) -
deliverable_content(NotBlankStr) -
agent_summary(NotBlankStr) -
acceptance_criteria(tuple[NotBlankStr, ...]) -
assigned_agent_id(NotBlankStr) -
autonomy(AutonomyLevel) -
stakes(Stakes) -
estimated_complexity(Complexity) -
project_id(NotBlankStr | None) -
produced_artifacts(tuple[DeliverableArtifact, ...])
Artifact¶
artifact
¶
Artifact domain models for task outputs and expected deliverables.
ArtifactType
¶
Bases: StrEnum
Type of produced artifact.
ExpectedArtifact
pydantic-model
¶
Bases: BaseModel
An artifact expected to be produced by a task.
Used within task definitions to declare what outputs are expected.
Attributes:
| Name | Type | Description |
|---|---|---|
type |
ArtifactType
|
The type of artifact expected. |
path |
NotBlankStr
|
File or directory path where the artifact should be produced. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
Artifact
pydantic-model
¶
Bases: BaseModel
A concrete artifact produced by an agent during task execution.
Artifacts track the actual work output, linking it back to the originating task and the agent who produced it.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
NotBlankStr
|
Unique artifact identifier (e.g. |
type |
ArtifactType
|
The type of artifact. |
path |
NotBlankStr
|
File or directory path of the artifact. |
task_id |
NotBlankStr
|
ID of the task that produced this artifact. |
created_by |
NotBlankStr
|
Agent ID of the creator. |
description |
str
|
Human-readable description of the artifact. |
content_type |
str
|
MIME content type (empty when no content stored). |
size_bytes |
int
|
Content size in bytes (zero when no content stored). |
project_id |
NotBlankStr | None
|
ID of the project this artifact belongs to. |
created_at |
AwareDatetime | None
|
Timestamp when the artifact was created. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(NotBlankStr) -
type(ArtifactType) -
path(NotBlankStr) -
task_id(NotBlankStr) -
created_by(NotBlankStr) -
description(str) -
project_id(NotBlankStr | None) -
content_type(str) -
size_bytes(int) -
created_at(AwareDatetime | None)
Personality¶
personality
¶
Personality compatibility scoring.
Computes pairwise and team-level compatibility scores from
:class:~synthorg.core.agent.PersonalityConfig profiles.
compute_compatibility
¶
Compute pairwise compatibility score between two personality profiles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
PersonalityConfig
|
First personality profile. |
required |
b
|
PersonalityConfig
|
Second personality profile. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Score between 0.0 (incompatible) and 1.0 (highly compatible). |
Source code in src/synthorg/core/personality.py
compute_team_compatibility
¶
Compute average pairwise compatibility for a team.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
members
|
tuple[PersonalityConfig, ...]
|
Tuple of personality profiles for team members. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Average pairwise score (1.0 for teams with fewer than 2 members). |
Source code in src/synthorg/core/personality.py
Resilience Config¶
resilience_config
¶
Resilience configuration models (retry + rate limiting).
Defined in core/ to avoid circular imports between config.schema
and providers.resilience. Both modules import from here.
RetryConfig
pydantic-model
¶
Bases: BaseModel
Configuration for automatic retry of transient provider errors.
Attributes:
| Name | Type | Description |
|---|---|---|
max_retries |
int
|
Maximum number of retry attempts (0 disables retries). |
base_delay |
float
|
Initial delay in seconds before the first retry. |
max_delay |
float
|
Upper bound on computed delay in seconds. |
exponential_base |
float
|
Multiplier for exponential backoff. |
jitter |
bool
|
Whether to add random jitter to delay. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
max_retries(int) -
base_delay(float) -
max_delay(float) -
exponential_base(float) -
jitter(bool)
Validators:
-
_validate_delay_ordering
RateLimiterConfig
pydantic-model
¶
Bases: BaseModel
Configuration for client-side rate limiting.
Attributes:
| Name | Type | Description |
|---|---|---|
max_requests_per_minute |
int
|
Maximum requests per minute (0 means unlimited). |
max_concurrent |
int
|
Maximum concurrent in-flight requests (0 means unlimited). |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
max_requests_per_minute(int) -
max_concurrent(int)
Auth¶
The auth domain types live in synthorg.core.auth (not synthorg.api.auth) so persistence repositories and engine modules can reference user / session / refresh-record / role models without crossing a layer boundary into the HTTP-coupled API package. The AuthService, controllers, and middleware that bind to Litestar / JWT issuer-audience constants stay under synthorg.api.auth.
config
¶
Authentication configuration.
AuthConfig
pydantic-model
¶
Bases: BaseModel
JWT and authentication configuration.
The jwt_secret is resolved at application startup via a
priority chain:
SYNTHORG_JWT_SECRETenvironment variable (for multi-instance deployments sharing a common secret).- Previously persisted secret in the
settingstable. - Auto-generate a new secret and persist it for future runs.
At construction time the secret may be empty -- it is populated before the first request is served.
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
jwt_secret(str) -
jwt_algorithm(Literal['HS256', 'HS384', 'HS512']) -
jwt_expiry_minutes(int) -
min_password_length(int) -
exclude_paths(tuple[str, ...] | None) -
dev_auth_bypass(bool) -
cookie_name(NotBlankStr) -
cookie_secure(bool) -
cookie_samesite(Literal['strict', 'lax', 'none']) -
cookie_path(NotBlankStr) -
csrf_cookie_path(NotBlankStr) -
cookie_domain(NotBlankStr | None) -
csrf_cookie_name(NotBlankStr) -
csrf_header_name(NotBlankStr) -
max_concurrent_sessions(int) -
jwt_refresh_enabled(bool) -
jwt_refresh_expiry_minutes(int) -
refresh_cookie_name(NotBlankStr) -
refresh_cookie_path(NotBlankStr) -
lockout_threshold(int) -
lockout_window_minutes(int) -
lockout_duration_minutes(int)
Validators:
-
_apply_mirrors -
_validate_secret_length -
_validate_refresh_expiry -
_validate_cookie_settings
jwt_secret
pydantic-field
¶
JWT signing secret (resolved at startup). Also used as the HMAC key for API key hash computation -- rotating this secret invalidates all stored API key hashes.
jwt_algorithm
pydantic-field
¶
JWT signing algorithm (HMAC family). HS256 is the default and is correctly keyed at the enforced MIN_SECRET_LENGTH (32 bytes); HS384/HS512 are accepted but RFC 7518 wants a >=48/64-byte key for full strength, so operators selecting them should provision a correspondingly longer jwt_secret.
jwt_expiry_minutes
pydantic-field
¶
Access-token lifetime in minutes (default 1h). Short by design: refresh-token rotation keeps sessions alive without long-lived bearer tokens.
min_password_length
pydantic-field
¶
Minimum password length for setup and password change
exclude_paths
pydantic-field
¶
Regex patterns for paths excluded from authentication. When None (default), paths are auto-derived from the API prefix (health, auth/setup, auth/login, docs, scalar UI). Use ^ to anchor at the start of the path and add $ when an exact match (rather than a prefix match) is required.
dev_auth_bypass
pydantic-field
¶
DEV ONLY. When True, the gated POST /auth/dev-login endpoint is live: it mints a real session for the existing admin with no password so local dev work skips the login screen. Resolved at startup from SYNTHORG_DEV_AUTH_BYPASS; defaults False and MUST never be enabled in production -- it lets anyone who can reach the API obtain an admin session. Auth enforcement is otherwise unchanged: only this one endpoint is gated on the flag.
csrf_cookie_path
pydantic-field
¶
Path scope for the CSRF cookie (non-HttpOnly). Defaults to / so document.cookie in JavaScript can read it from any SPA route; scoping it under /api (like the session cookie) would hide it from code running on application pages, breaking the double-submit pattern.
cookie_domain
pydantic-field
¶
Domain for session cookies (None = current host)
csrf_cookie_name
pydantic-field
¶
CSRF token cookie name (non-HttpOnly, JS-readable)
csrf_header_name
pydantic-field
¶
Header name for CSRF token submission
max_concurrent_sessions
pydantic-field
¶
Max concurrent sessions per user (0 = unlimited)
jwt_refresh_expiry_minutes
pydantic-field
¶
Refresh token lifetime in minutes (default 7 days)
refresh_cookie_name
pydantic-field
¶
Refresh token cookie name
refresh_cookie_path
pydantic-field
¶
Path scope for refresh token cookie (narrow)
lockout_threshold
pydantic-field
¶
Failed login attempts before account lockout
lockout_window_minutes
pydantic-field
¶
Sliding window for counting failed attempts
lockout_duration_minutes
pydantic-field
¶
Auto-unlock duration after lockout
with_secret
¶
Return a copy with the JWT secret set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
secret
|
str
|
Resolved JWT signing secret. |
required |
Returns:
| Type | Description |
|---|---|
AuthConfig
|
New |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the secret is too short for the configured JWT algorithm. |
Source code in src/synthorg/core/auth/config.py
models
¶
Authentication domain models.
AuthMethod
¶
Bases: StrEnum
Authentication method used for a request.
OrgRole
¶
Bases: StrEnum
Permission-level role for org configuration access.
Orthogonal to HumanRole (operational persona).
HumanRole controls who you are in the org simulation;
OrgRole controls what you can do to the org config.
User
pydantic-model
¶
Bases: BaseModel
Persisted user account.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
NotBlankStr
|
Unique user identifier. |
username |
NotBlankStr
|
Login username. |
password_hash |
str
|
Argon2id hash (excluded from repr). |
role |
HumanRole
|
Access control role. |
must_change_password |
bool
|
Whether the user must change password. |
org_roles |
tuple[OrgRole, ...]
|
Permission-level roles for org config access. |
scoped_departments |
tuple[NotBlankStr, ...]
|
Departments accessible to dept admins. |
created_at |
AwareDatetime
|
Account creation timestamp. |
updated_at |
AwareDatetime
|
Last modification timestamp. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(NotBlankStr) -
username(NotBlankStr) -
password_hash(str) -
role(HumanRole) -
must_change_password(bool) -
org_roles(tuple[OrgRole, ...]) -
scoped_departments(tuple[NotBlankStr, ...]) -
created_at(AwareDatetime) -
updated_at(AwareDatetime)
Validators:
-
_validate_scoped_departments
ApiKey
pydantic-model
¶
Bases: BaseModel
Persisted API key (hash-only storage).
Attributes:
| Name | Type | Description |
|---|---|---|
id |
NotBlankStr
|
Unique key identifier (UUID). |
key_hash |
NotBlankStr
|
HMAC-SHA256 hex digest of the raw key. |
name |
NotBlankStr
|
Human-readable label. |
role |
HumanRole
|
Access control role. |
user_id |
NotBlankStr
|
Owner user ID. |
created_at |
AwareDatetime
|
Key creation timestamp (timezone-aware). |
expires_at |
AwareDatetime | None
|
Optional expiry timestamp (timezone-aware). |
revoked |
bool
|
Whether the key has been revoked. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
id(NotBlankStr) -
key_hash(NotBlankStr) -
name(NotBlankStr) -
role(HumanRole) -
user_id(NotBlankStr) -
created_at(AwareDatetime) -
expires_at(AwareDatetime | None) -
revoked(bool)
AuthenticatedUser
pydantic-model
¶
Bases: BaseModel
Lightweight identity attached to connection.user.
Populated by the auth middleware after successful authentication.
Attributes:
| Name | Type | Description |
|---|---|---|
user_id |
NotBlankStr
|
User's unique identifier. |
username |
NotBlankStr
|
User's login name. |
role |
HumanRole
|
Access control role. |
auth_method |
AuthMethod
|
How the user authenticated. |
must_change_password |
bool
|
Whether forced password change is pending. |
org_roles |
tuple[OrgRole, ...]
|
Permission-level roles for org config access. |
scoped_departments |
tuple[NotBlankStr, ...]
|
Departments accessible to dept admins. |
session_id |
NotBlankStr | None
|
JWT |
api_key_id |
NotBlankStr | None
|
Id of the API key that authenticated the request
(or |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
user_id(NotBlankStr) -
username(NotBlankStr) -
role(HumanRole) -
auth_method(AuthMethod) -
must_change_password(bool) -
org_roles(tuple[OrgRole, ...]) -
scoped_departments(tuple[NotBlankStr, ...]) -
session_id(NotBlankStr | None) -
api_key_id(NotBlankStr | None)
Validators:
-
_validate_api_key_binding -
_validate_scoped_departments
session
¶
Session domain model for JWT session tracking.
Session
pydantic-model
¶
Bases: BaseModel
An active JWT session.
Each JWT token issued at login/setup creates a Session
record. The session_id corresponds to the JWT jti
claim, enabling per-token revocation.
Attributes:
| Name | Type | Description |
|---|---|---|
session_id |
NotBlankStr
|
JWT |
user_id |
NotBlankStr
|
Owner's user ID. |
username |
NotBlankStr
|
Owner's login name (denormalized for display). |
role |
HumanRole
|
Owner's role at session creation time. |
ip_address |
str
|
Client IP at login time. |
user_agent |
str
|
Client User-Agent header at login time (capped at 512 characters). |
created_at |
AwareDatetime
|
Session creation timestamp. |
last_active_at |
AwareDatetime
|
Last request timestamp. |
expires_at |
AwareDatetime
|
JWT expiry timestamp. |
revoked |
bool
|
Whether the session has been revoked. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
session_id(NotBlankStr) -
user_id(NotBlankStr) -
username(NotBlankStr) -
role(HumanRole) -
ip_address(str) -
user_agent(str) -
created_at(AwareDatetime) -
last_active_at(AwareDatetime) -
expires_at(AwareDatetime) -
revoked(bool)
Validators:
-
_validate_temporal_ordering
refresh_record
¶
Refresh-token record model.
Lives outside the persistence layer so protocol modules can depend on the model without importing a backend implementation.
RefreshRejectReason
¶
Bases: StrEnum
Why a consume() call refused to mint a new lease.
The repository captures the reason as a typed enum so the auth
service / controller can emit SECURITY_AUTH_REFRESH_REJECTED
with the correct reason field instead of folding every miss
into a single bucket.
RefreshConsumeOutcome
pydantic-model
¶
Bases: BaseModel
Result of a refresh-token consume attempt.
Exactly one of record and reject_reason is populated.
The model validator below keeps the discriminator honest.
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
record(RefreshRecord | None) -
reject_reason(RefreshRejectReason | None)
Validators:
-
_validate_discriminator
RefreshRecord
pydantic-model
¶
Bases: BaseModel
A stored refresh token record.
Attributes:
| Name | Type | Description |
|---|---|---|
token_hash |
NotBlankStr
|
HMAC-SHA256 hash of the opaque token. |
session_id |
NotBlankStr
|
Associated JWT session ( |
user_id |
NotBlankStr
|
Token owner's user ID. |
expires_at |
AwareDatetime
|
Expiry timestamp. |
used |
bool
|
Whether the token has been consumed. |
created_at |
AwareDatetime
|
Creation timestamp. |
Config:
frozen:Trueallow_inf_nan:Falseextra:forbid
Fields:
-
token_hash(NotBlankStr) -
session_id(NotBlankStr) -
user_id(NotBlankStr) -
expires_at(AwareDatetime) -
used(bool) -
created_at(AwareDatetime)
Validators:
-
_validate_temporal_order