Skip to content

World Spec API

The world-runner exposes a small set of admin-only HTTP endpoints for uploading and activating world and region specs at runtime — no restart required.

All endpoints require an authenticated session with the Admin role. Unauthenticated requests receive 401 Unauthorized; non-admin sessions receive 403 Forbidden.


Region Specs

A region spec is a YAML document that describes a single region (geometry, tile materials, tags, etc.). Regions must be uploaded before a world spec that references them.

Upload a region spec

POST /spec/region
Content-Type: application/x-yaml

Body: Raw YAML of the region spec. The spec must contain a meta.genome field — this is the canonical identifier used for all subsequent lookups.

Success — 200 OK

{
  "name": "amboseli",
  "title": "Amboseli Basin",
  "genome": "01a2fc988f4dee38"
}

Errors

Status error field Meaning
400 invalid_utf8 Body is not valid UTF-8
422 invalid_region_spec YAML is malformed or missing required fields

Retrieve a region spec

GET /spec/region/{genome}

Returns the raw YAML that was uploaded for the given genome, or 404 if not found.

Success — 200 OK

Content-Type: application/x-yaml; charset=utf-8

meta:
  genome: "01a2fc988f4dee38"
  name: amboseli
  ...

Errors

Status error field Meaning
404 not_found No region spec stored for this genome

World Specs

A world spec declares which regions compose the active world, using short alias names that reference uploaded region specs.

Provision a world

POST /world/spec
Content-Type: application/x-yaml

Body: Raw YAML of the world spec. The spec must declare world_id and a refs.regions map whose keys are the alias names used inside regions.

What this endpoint does:

  1. Parses and validates the world spec YAML.
  2. Resolves each region alias against the in-memory spec store (by ref alias → name → genome). Returns 422 immediately if any alias cannot be resolved.
  3. Pauses a running continuous clock (resumed unconditionally when the operation finishes).
  4. Atomically replaces the live region registry with the newly built one.
  5. Stores the world YAML as the active world; subsequent GET /world/spec returns it.

Success — 200 OK

{
  "world_id": "starter_world",
  "region_count": 2,
  "regions": ["amboseli", "pictou"]
}

Errors

Status error field Meaning
400 invalid_utf8 Body is not valid UTF-8
422 invalid_world_spec YAML is malformed or missing required fields
422 missing_region_refs One or more region aliases have not been uploaded yet. The response includes a missing_refs array.
409 clock_pause_failed The running clock could not be paused before the swap
422 world_provision_failed The registry replacement step itself failed
500 world_replace_task_failed An internal async task panic occurred

Missing refs example:

{
  "error": "missing_region_refs",
  "missing_refs": ["pictou"]
}

Upload the missing region specs and retry.


Retrieve the active world spec

GET /world/spec

Returns the raw YAML of the most recently provisioned world spec.

Success — 200 OK

Content-Type: application/x-yaml; charset=utf-8

world_id: starter_world
refs:
  regions:
    amboseli: ...
    pictou: ...

Errors

Status error field Meaning
404 not_found No world has been provisioned yet

Typical provisioning flow

# 1. Authenticate and obtain a session token
TOKEN=$(curl -sX POST http://localhost:8080/token -d '{"admin_secret":"..."}' | jq -r .token)

# 2. Upload each region spec
curl -X POST http://localhost:8080/spec/region \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/x-yaml" \
     --data-binary @regions/amboseli.yaml

curl -X POST http://localhost:8080/spec/region \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/x-yaml" \
     --data-binary @regions/pictou.yaml

# 3. Retrieve a region spec to verify
curl -H "Authorization: Bearer $TOKEN" \
     http://localhost:8080/spec/region/01a2fc988f4dee38

# 4. Provision the world
curl -X POST http://localhost:8080/world/spec \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/x-yaml" \
     --data-binary @worlds/starter_world.yaml

# 5. Verify the active world
curl -H "Authorization: Bearer $TOKEN" \
     http://localhost:8080/world/spec

Genome — the canonical identity

meta.genome in a region spec is the single source of truth for that region's identity. It is a stable, opaque hex string generated once and embedded in the spec file itself.

  • Upload uses meta.genome from the body — there is no genome in the POST path.
  • Retrieval addresses by genome: GET /spec/region/{genome}.
  • World specs reference regions by short alias names (e.g. amboseli). The provisioning step resolves aliases to genomes automatically.

This means renaming an alias in a world spec without changing the underlying spec file is safe — the genome is unaffected.


Generic Spec Endpoints

Alongside dedicated world and region APIs, the runner exposes generalized spec storage and instantiation endpoints.

Upload any registered kind

POST /spec/{kind}
Content-Type: application/x-yaml

Returns:

{
  "kind": "simulation.vehicle",
  "id": "beatle_test_001"
}

Retrieve by kind and id

GET /spec/{kind}/{id}

Returns raw YAML.

List ids for a kind

GET /spec/{kind}

Returns:

{
  "kind": "simulation.vehicle",
  "ids": ["beatle_test_001"]
}

Instantiate a stored spec

POST /spec/{kind}/{id}/instantiate

Whitelisted instantiable kinds:

  • simulation.vehicle
  • earth.animal
  • simulation.region
  • social.fate

Storage-only kinds return 422 with error not_instantiable.

Example vehicle response:

{
  "kind": "simulation.vehicle",
  "id": "beatle_test_001",
  "instance": {
    "vehicle_id": "beatle_test_001-...",
    "genome": "...",
    "architecture": "...",
    "region_id": "coreland"
  }
}

Notes

  • The spec store is in-memory only. Uploaded specs do not persist across world-runner restarts. Re-upload region specs and re-provision the world after a restart (or pass --world-spec at startup to seed from disk).
  • Provisioning is atomic: either the full registry is replaced or the existing registry is left intact and an error is returned.
  • Clock management is transparent: if the simulation clock is running in continuous mode it is paused during the swap and resumed (or left paused on error) — callers do not need to pause manually.
  • Schema fixture and document resolution conventions are described in runtime/schema-discovery.