Schemas¶
The Pydantic models that define install.yaml (xcore_agent.schema.install)
and manifest.json (xcore_agent.schema.manifest).
install.yaml — install plan & steps¶
xcore_agent.schema.install
¶
Schema and validation for install.yaml — the deployment plan shipped inside
a .xdeploy artifact.
Every step's action is restricted to a fixed, closed enum of verbs the agent
knows how to execute safely. There is intentionally no generic "run a shell
command" action: a malicious or tampered artifact must not be able to turn
xcore-agent into an arbitrary remote-execution primitive.
Step = Annotated[Union[PrepareStep, DownloadStep, ExtractStep, ProvisionStep, InstallPluginStep, InstallExtensionStep, ConfigurePluginStep, WriteEnvStep, NotifyStep, StartStep, StopStep, RestartStep, HealthcheckStep, RollbackStep], Field(discriminator='action')]
module-attribute
¶
PrepareStep
¶
Bases: _StepBase
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
depends_on: list[str] = Field(default_factory=list)
class-attribute
instance-attribute
¶
snapshot: bool = False
class-attribute
instance-attribute
¶
action: Literal['prepare'] = 'prepare'
class-attribute
instance-attribute
¶
DownloadStep
¶
Bases: _StepBase
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
depends_on: list[str] = Field(default_factory=list)
class-attribute
instance-attribute
¶
snapshot: bool = False
class-attribute
instance-attribute
¶
action: Literal['download'] = 'download'
class-attribute
instance-attribute
¶
ExtractStep
¶
Bases: _StepBase
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
depends_on: list[str] = Field(default_factory=list)
class-attribute
instance-attribute
¶
snapshot: bool = False
class-attribute
instance-attribute
¶
action: Literal['extract'] = 'extract'
class-attribute
instance-attribute
¶
ProvisionStep
¶
Bases: _PluginStepBase
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
depends_on: list[str] = Field(default_factory=list)
class-attribute
instance-attribute
¶
snapshot: bool = False
class-attribute
instance-attribute
¶
plugin: str
instance-attribute
¶
action: Literal['provision'] = 'provision'
class-attribute
instance-attribute
¶
InstallPluginStep
¶
Bases: _PluginStepBase
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
depends_on: list[str] = Field(default_factory=list)
class-attribute
instance-attribute
¶
snapshot: bool = False
class-attribute
instance-attribute
¶
plugin: str
instance-attribute
¶
action: Literal['install_plugin'] = 'install_plugin'
class-attribute
instance-attribute
¶
source: PluginSource | None = None
class-attribute
instance-attribute
¶
InstallExtensionStep
¶
Bases: _ExtensionStepBase
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
depends_on: list[str] = Field(default_factory=list)
class-attribute
instance-attribute
¶
snapshot: bool = False
class-attribute
instance-attribute
¶
extension: str
instance-attribute
¶
action: Literal['install_extension'] = 'install_extension'
class-attribute
instance-attribute
¶
source: PluginSource | None = None
class-attribute
instance-attribute
¶
NotifyStep
¶
Bases: _StepBase
Tells the agent's notify() a named event happened at this point in
the plan — never a URL/webhook/recipient itself (same reasoning as
ProvisionStep.plugin: the artifact only supplies an opaque label, the
real destination is host-side operator config, see agent.notifiers).
A missing or failing notifier never fails the deployment — notifying is
a side channel, not part of what makes an install succeed or fail.
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
depends_on: list[str] = Field(default_factory=list)
class-attribute
instance-attribute
¶
snapshot: bool = False
class-attribute
instance-attribute
¶
action: Literal['notify'] = 'notify'
class-attribute
instance-attribute
¶
event: str
instance-attribute
¶
message: str | None = None
class-attribute
instance-attribute
¶
ConfigurePluginStep
¶
Bases: _PluginStepBase
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
depends_on: list[str] = Field(default_factory=list)
class-attribute
instance-attribute
¶
snapshot: bool = False
class-attribute
instance-attribute
¶
plugin: str
instance-attribute
¶
action: Literal['configure_plugin'] = 'configure_plugin'
class-attribute
instance-attribute
¶
WriteEnvStep
¶
Bases: _PluginStepBase
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
depends_on: list[str] = Field(default_factory=list)
class-attribute
instance-attribute
¶
snapshot: bool = False
class-attribute
instance-attribute
¶
plugin: str
instance-attribute
¶
action: Literal['write_env'] = 'write_env'
class-attribute
instance-attribute
¶
from_: str = Field(..., alias='from')
class-attribute
instance-attribute
¶
StartStep
¶
Bases: _StepBase
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
depends_on: list[str] = Field(default_factory=list)
class-attribute
instance-attribute
¶
snapshot: bool = False
class-attribute
instance-attribute
¶
action: Literal['start'] = 'start'
class-attribute
instance-attribute
¶
plugin: str | None = None
class-attribute
instance-attribute
¶
StopStep
¶
Bases: _StepBase
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
depends_on: list[str] = Field(default_factory=list)
class-attribute
instance-attribute
¶
snapshot: bool = False
class-attribute
instance-attribute
¶
action: Literal['stop'] = 'stop'
class-attribute
instance-attribute
¶
plugin: str | None = None
class-attribute
instance-attribute
¶
RestartStep
¶
Bases: _StepBase
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
depends_on: list[str] = Field(default_factory=list)
class-attribute
instance-attribute
¶
snapshot: bool = False
class-attribute
instance-attribute
¶
action: Literal['restart'] = 'restart'
class-attribute
instance-attribute
¶
plugin: str | None = None
class-attribute
instance-attribute
¶
HealthcheckStep
¶
Bases: _StepBase
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
depends_on: list[str] = Field(default_factory=list)
class-attribute
instance-attribute
¶
snapshot: bool = False
class-attribute
instance-attribute
¶
action: Literal['healthcheck'] = 'healthcheck'
class-attribute
instance-attribute
¶
plugin: str | None = None
class-attribute
instance-attribute
¶
timeout_seconds: int = Field(default=30, gt=0, le=600, alias='timeout')
class-attribute
instance-attribute
¶
retries: int = Field(default=3, ge=0, le=20)
class-attribute
instance-attribute
¶
RollbackStep
¶
Bases: _StepBase
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
depends_on: list[str] = Field(default_factory=list)
class-attribute
instance-attribute
¶
snapshot: bool = False
class-attribute
instance-attribute
¶
action: Literal['rollback'] = 'rollback'
class-attribute
instance-attribute
¶
to: str | None = None
class-attribute
instance-attribute
¶
InstallPlan
¶
Bases: BaseModel
Parsed, validated install.yaml.
Source code in xcore_agent/schema/install.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
format_version: Literal['1']
instance-attribute
¶
project_id: str
instance-attribute
¶
version: str
instance-attribute
¶
steps: list[Step] = Field(..., min_length=1)
class-attribute
instance-attribute
¶
execution_order() -> list[str]
¶
Return step ids in an order that respects every depends_on edge.
manifest.json — project & plugin manifest¶
xcore_agent.schema.manifest
¶
Schema for manifest.json — the plaintext description of a .xdeploy artifact's
contents, hashed and referenced by the outer signature so the agent can verify
what it received matches what was built, independently of the encryption layer.
EnvironmentSpec
¶
Bases: BaseModel
A plugin's declared .env contract — which variables the host
operator must fill in before the plugin can start. write_env
(agent/install_driver.py) checks required against the actual env
file after seeding it from the template.
Source code in xcore_agent/schema/manifest.py
PluginSource
¶
Bases: BaseModel
Where to fetch a plugin's code from instead of (or in addition to)
what's embedded in the .xdeploy artifact — typically handed out by a
marketplace/registry as a resolvable link.
Exactly one origin, not both:
- Marketplace (preferred) —
marketplace_slug(+ optionalmarketplace_version/marketplace_kind). Resolved at deploy time via the real xcore-team/marketplaceGET /{slug}/installendpoint (agent.marketplace_client.MarketplaceClient), whose response is HMAC-SHA256-signed — seeplugin_resolver.PluginResolver._resolve_ marketplace. This isxcli's default when it writes.xcore- registry.jsonfor a plugin installed from the marketplace (seexcli'sshared.record_install): the marketplace is the authoritative origin for anything published there, not an alternative to git. - Git (fallback) —
url+ref, for a plugin never published to the marketplace (an operator's own private fork, something still under development).refshould be a commit SHA whenever integrity matters: it's the only form that's content-addressed, so pinning to one letsPluginRef.sha256(computed over the resolved tree) actually mean something. A branch or tag is mutable — the code behind it can change withoutsha256in the manifest ever being updated, silently defeating the tamper check.
A marketplace-sourced plugin gets an equivalent integrity guarantee for
free from the HMAC signature itself (verified against the publisher's
signing_secret on every fetch), independently of whether PluginRef.
sha256 is also pinned.
Source code in xcore_agent/schema/manifest.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
marketplace_slug: str | None = None
class-attribute
instance-attribute
¶
marketplace_version: str = 'latest'
class-attribute
instance-attribute
¶
marketplace_kind: Literal['plugin', 'service'] = 'plugin'
class-attribute
instance-attribute
¶
url: str | None = None
class-attribute
instance-attribute
¶
ref: str | None = None
class-attribute
instance-attribute
¶
subdirectory: str | None = None
class-attribute
instance-attribute
¶
PluginRef
¶
Bases: BaseModel
Source code in xcore_agent/schema/manifest.py
model_config = {'extra': 'forbid'}
class-attribute
instance-attribute
¶
id: str
instance-attribute
¶
version: str
instance-attribute
¶
sha256: str | None = None
class-attribute
instance-attribute
¶
environment: EnvironmentSpec | None = None
class-attribute
instance-attribute
¶
source: PluginSource | None = None
class-attribute
instance-attribute
¶
ExtensionRef
¶
Bases: BaseModel
A shared, non-plugin service bundled into the artifact (e.g.
extensions/xmailler) — embedded by default, OR resolved from git at
deploy time via source (see extensions/<id>/extension.yaml —
PluginSource reused verbatim; the field name stays source for
symmetry with PluginRef.source, there's nothing plugin-specific about
it). Same rule as PluginRef: sha256 is required unless source is
set — nothing to hash for a repo the packer never fetches at build time.
Source code in xcore_agent/schema/manifest.py
ProjectManifest
¶
Bases: BaseModel
Describes one built version of a project's .xdeploy artifact.