Skip to main content

Python author kit for Astraform remote-domain.v1 services

Project description

astraform-remote-domain-author-kit

This is the Python author kit for remote-domain.v1.

Brutal truth: an "SDK" alone is not enough. If teams still have to reverse engineer request envelopes, invent their own starter layout, or guess how to prove conformance, you did not ship onboarding. You shipped homework.

This author kit is broader than a thin SDK. It includes:

  • reusable protocol constants and envelope builders
  • request validation helpers
  • an optional FastAPI app factory
  • a starter template inside the package

If you only want helper functions, that is the SDK-like layer. The author kit is the whole package around it.

Install

Current status: the published PyPI baseline is astraform-remote-domain-author-kit==0.1.0. The workspace release target is 0.1.2, which adds the current Population Builder catalog/readiness starter shape. Do not claim external Python catalog authoring support until 0.1.2 is actually published to PyPI.

Protocol helpers only:

pip install astraform-remote-domain-author-kit==0.1.0

FastAPI helper included:

pip install 'astraform-remote-domain-author-kit[fastapi]==0.1.0'

For catalog-enabled 0.1.2 work before publication, use the monorepo editable install or a private pre-release wheel.

Repo-local development:

pip install -e './remote-domain-author-kit-python[fastapi,test]'

Starter-template validation is part of the release gate. It still runs the template's scripts/bootstrap-local-sdk.sh path against the repo-local SDK source, then separately runs an external-consumer smoke from the exact built local author-kit and conformance wheels. That smoke creates a clean project, copies the starter through the installed astraform-remote-domain-copy-starter command, installs the copied starter with --no-deps, runs validate-population-catalog, and passes remote-domain-conformance --population-catalog. That keeps the source bootstrap and release artifact paths honest before the matching SDK version is visible on PyPI.

Core Usage

from astraform.remote_domain.author_kit.protocol import build_manifest
from astraform.remote_domain.author_kit.protocol import build_projection
from astraform.remote_domain.author_kit.protocol import opaque_state
from astraform.remote_domain.author_kit.protocol import projection_envelope
from astraform.remote_domain.author_kit.protocol import success_envelope
from astraform.remote_domain.author_kit.protocol import validate_request_envelope


def manifest() -> dict:
    return build_manifest(
        domain_id="acme-ops",
        display_name="Acme Operations Domain",
        description="Remote proof domain",
        schema_version="acme-ops.state.v1",
        supported_agent_types=["Operator"],
        supported_interaction_modes=["SIMULATION", "HYBRID"],
        tools=[
            {
                "name": "lookup_case",
                "description": "Look up a case in the remote domain.",
                "inputSchema": {"type": "object", "additionalProperties": False},
            }
        ],
    )


def prepare(request: dict) -> dict:
    validate_request_envelope(
        request,
        expected_domain_id="acme-ops",
        expected_operation="prepare",
        require_idempotency=True,
    )
    state = opaque_state(
        "acme-ops.state.v1",
        {"personaName": "Taylor", "completedWorkCount": 0},
    )
    projection = build_projection(
        runtime_metadata={"domainProfile": "acme"},
        status_view={"completedWorkCount": 0},
        inspection_view={"tasks": []},
    )
    return success_envelope(
        request,
        runtime_identity="acme-ops::Taylor",
        next_state=state,
        projection=projection,
    )


def status(request: dict) -> dict:
    validate_request_envelope(
        request,
        expected_domain_id="acme-ops",
        expected_operation="status",
        require_state=True,
    )
    return projection_envelope(
        request,
        projection=build_projection(
            runtime_metadata={"domainProfile": "acme"},
            status_view={"completedWorkCount": 0},
            inspection_view={"tasks": []},
        ),
    )

Domain providers may add optional evidence_events=[...] to success_envelope(...) or projection_envelope(...). Use that lane for provider-internal evidence that Astraform cannot observe directly, such as a private third-party call or domain-owned policy check.

FastAPI App Factory

from astraform.remote_domain.author_kit.fastapi import create_fastapi_app

app = create_fastapi_app(
    service=my_remote_domain_service,
    policy_wind_tunnel_service=my_policy_wind_tunnel_service,
)

The service object must implement:

  • manifest()
  • optional population_catalog() for GET /api/remote-domain/v1/population/catalog
  • prepare(payload)
  • execute_work(payload)
  • status(payload)
  • inspection(payload)
  • shutdown(payload)

population_catalog() must return domain_population_catalog.v1. The FastAPI factory validates the catalog before returning it, so missing archetype fields, bad recipe numbers, unknown archetype references, and malformed eligibility fail before Population Builder treats the provider as usable.

Prefer a file-backed catalog over an inline Python dict. That keeps the domain authoring surface reviewable and conformance-testable:

from importlib import resources

from astraform.remote_domain.author_kit import load_population_catalog


def population_catalog() -> dict:
    catalog_file = resources.files("my_remote_domain").joinpath("population_catalog.json")
    return load_population_catalog(catalog_file)

load_population_catalog(...) reads JSON and runs the same validate_population_catalog(...) checks used by the FastAPI route.

The bundled fastapi-minimal starter also installs a provider-local preflight:

validate-population-catalog

That command validates src/acme_remote_domain/population_catalog.json before the provider starts and prints the exact rejected field when the catalog is malformed. Treat it as the first command after editing archetypes, segment templates, validation rules, or run-path eligibility.

The optional policy_wind_tunnel_service object exposes the remote Wind Tunnel provider routes:

  • GET /policy-wind-tunnel/pack
  • GET /policy-wind-tunnel/presets
  • POST /policy-wind-tunnel/runs
  • GET /policy-wind-tunnel/runs/{runId}
  • POST /policy-wind-tunnel/runs/{runId}/lifecycle
  • GET /policy-wind-tunnel/runs/{runId}/bundle
  • GET /policy-wind-tunnel/runs/{runId}/artifacts/{artifactType}
  • GET /policy-wind-tunnel/runs/{runId}/artifacts/{artifactType}/readiness
  • GET /policy-wind-tunnel/runs/{runId}/evidence-pack
  • GET /policy-wind-tunnel/runs/{runId}/evidence-pack/readiness

The readiness routes are metadata-only checks for dashboard download UX. They must prove the same provider-owned artifact/evidence-pack path is readable without materializing the JSON body or ZIP archive.

Policy Expressions

When a domain exposes Policy Wind Tunnel behavior, CEL-compatible PolicyExpression definitions are the portable decision contract. They are for decision gates, eligibility checks, thresholds, and conformance-testable public rules.

They are not the execution engine. Keep state mutation, external calls, proprietary scoring, and side effects inside your service implementation or domain-owned execution target. Use the expression's executionTarget as a stable provider-owned target name.

Python providers should publish the same /policy-wind-tunnel/pack metadata as Java providers. The helper below builds the portable parts of that response:

from astraform.remote_domain.author_kit import build_policy_expression
from astraform.remote_domain.author_kit import build_policy_wind_tunnel_pack_metadata


def wind_tunnel_pack() -> dict:
    return build_policy_wind_tunnel_pack_metadata(
        capabilities={"remoteProviderReady": True, "evidenceExport": True},
        control_schema={
            "type": "object",
            "properties": {
                "blockerCount": {"type": "integer", "minimum": 0},
            },
        },
        ui_schema={
            "fields": [
                {"name": "blockerCount", "widget": "number", "label": "Blockers"},
            ],
        },
        outcome_schema={
            "schemaVersion": "domain_outcome_schema.v1",
            "metricDefinitions": [
                {
                    "metricId": "blockerCount",
                    "label": "Blockers",
                    "unit": "count",
                    "evidence": "domain-state",
                },
            ],
        },
        domain_labels={
            "actorSingular": "campaign",
            "actorPlural": "campaigns",
            "simulatedActorsLabel": "Simulated campaigns",
        },
        policy_expressions=[
            build_policy_expression(
                expression_id="acme.blockers.acceptable",
                expression="metrics.blockerCount <= 10",
                execution_target="acme-policy-service",
                description="Blockers must stay under launch threshold.",
            ),
        ],
    )

See docs/architecture/scenario-lab-policy-expressions.md for the contract shape and CEL subset.

Starter Template

Copy the bundled FastAPI starter from the installed author kit:

astraform-remote-domain-copy-starter acme-remote-domain
cd acme-remote-domain
pip install --no-deps -e .
validate-population-catalog
remote-domain-conformance --app acme_remote_domain.main:app --domain-id acme-remote --population-catalog

The underlying template resource lives under:

  • astraform/remote_domain/author_kit/templates/fastapi-minimal

It is intentionally boring. That is a feature. Teams need a truthful starting point, not a framework demo that hides the protocol.

Publishing Status

This package is released through the shared Python + Java SDK publishing process documented in docs/platform/remote-domain-sdk-publishing.md.

Release guardrail:

SDK_VERSION=0.1.2 scripts/check-remote-domain-sdk-release-gates.sh

PyPI artifacts are immutable. Do not rerun a publish for an already published version; run smoke-only verification or bump the SDK version.

Public package note: PyPI distributions expose this SDK implementation. Keep host runtime internals and domain-private logic out of this package.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

astraform_remote_domain_author_kit-0.1.2.tar.gz (30.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file astraform_remote_domain_author_kit-0.1.2.tar.gz.

File metadata

File hashes

Hashes for astraform_remote_domain_author_kit-0.1.2.tar.gz
Algorithm Hash digest
SHA256 df32b42c02e50a98ef31539c4ac20308ab2be701c303697a5db9d4b573b4c129
MD5 95d4aa36a611f5fd31a44ad9ee1eda8f
BLAKE2b-256 294a8a171da2d8150fa191c3ba79ad2c7ad77ced5aede82bb68bb0d0a56d2cbc

See more details on using hashes here.

Provenance

The following attestation bundles were made for astraform_remote_domain_author_kit-0.1.2.tar.gz:

Publisher: remote_domain_sdk_release.yml on astraform/platform

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file astraform_remote_domain_author_kit-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for astraform_remote_domain_author_kit-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8a027a627217595ac188e0d9396a5463b952dbc7595f73294a4dd085d1c5cd4f
MD5 7a23a293033c65d86e20e21e5fe84751
BLAKE2b-256 905e4eab1d58abb79ad5410da363953bebc5262515691fcc09270abaffe52425

See more details on using hashes here.

Provenance

The following attestation bundles were made for astraform_remote_domain_author_kit-0.1.2-py3-none-any.whl:

Publisher: remote_domain_sdk_release.yml on astraform/platform

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page