5.6 KiB
5.6 KiB
amduatd API v2 Design (PEL-only writes)
Status
Draft proposal for discussion.
First server slice implemented: POST /v2/pel/execute with inputs.refs,
inputs.inline_artifacts[{body_hex,type_tag?}], and required receipt.
Goals
- Keep
amduatdthin: transport, parsing, auth, and mapping to core calls. - Make PEL the only write primitive in HTTP v2.
- Enforce artifact provenance for writes: adding new artifacts must go through:
- store inputs,
- run a PEL program,
- persist and return receipt.
- Keep
/v1/*behavior unchanged while v2 is introduced.
Non-goals
- Re-implementing PEL semantics in
amduat-api. - Creating new substrate semantics in daemon code.
- Removing v1 immediately.
High-level model
v2 separates read and write concerns:
- Read paths remain direct and deterministic (
GET /v2/meta,GET /v2/artifacts/{ref}, federation/space read endpoints). - All state-changing operations are executed as PEL runs.
In v2, POST /v1/artifacts equivalent is replaced by a mutation endpoint that always drives a PEL run.
For simplified clients, v2 also exposes async operation endpoints:
POST /v2/ops/putPOST /v2/ops/concatPOST /v2/ops/sliceGET /v2/jobs/{id}
These enqueue work and execute PEL in the daemon background loop.
Graph-oriented endpoints can be added as thin wrappers over concepts/relations:
POST /v2/graph/nodes(maps to concept create/publish)POST /v2/graph/edges(maps to relation edge append)GET /v2/graph/nodes/{name}(node + versions + incoming/outgoing edges)GET /v2/graph/history/{name}(version + edge timeline)
Versioning and contract id
- Base path:
/v2 - Contract id:
AMDUATD/API/2 - Keep the same store-seeded contract model used in v1.
Endpoint shape
Read-only endpoints (v2)
GET /v2/metaGET /v2/contractGET /v2/artifacts/{ref}HEAD /v2/artifacts/{ref}GET /v2/artifacts/{ref}?format=info- Space/federation read endpoints can be mirrored under
/v2/*unchanged where possible.
Write endpoints (v2)
POST /v2/pel/execute
No direct artifact write endpoint in v2 (POST /v2/artifacts is intentionally absent).
POST /v2/pel/execute
Single mutation primitive for v2.
Request
{
"program_ref": "<hex-ref-or-name>",
"scheme_ref": "dag",
"params_ref": "<optional-ref-or-name>",
"inputs": {
"refs": ["<hex-ref-or-name>"],
"inline_artifacts": [
{
"content_type": "application/octet-stream",
"type_tag": "0x00000000",
"body_hex": "48656c6c6f"
}
]
},
"receipt": {
"input_manifest_ref": "<ref-or-name>",
"environment_ref": "<ref-or-name>",
"evaluator_id": "local-amduatd",
"executor_ref": "<ref-or-name>",
"started_at": 1731000000,
"completed_at": 1731000005
},
"effects": {
"publish_outputs": true,
"append_fed_log": true
}
}
Processing contract
Server behavior is deterministic and ordered:
- Resolve
program_ref,scheme_ref,params_ref, andinputs.refsto refs. - Decode and store
inputs.inline_artifactsinto ASL store. - Build effective
input_refs = refs + stored_inline_refs. - Execute PEL using core
pel_surf_run_with_result. - Build FER receipt from run result + receipt fields.
- Store receipt artifact and return
receipt_ref. - Apply requested side effects (
publish_outputs,append_fed_log) after successful run.
If any step fails:
- return non-2xx,
- do not publish outputs,
- do not append federation publish records.
Response
{
"run_ref": "<pel1-result-ref>",
"trace_ref": "<optional-trace-ref>",
"receipt_ref": "<fer1-receipt-ref>",
"stored_input_refs": ["<ref>"],
"output_refs": ["<ref>"],
"status": "OK"
}
Notes:
stored_input_refsare refs created frominline_artifacts.receipt_refis required for successful writes in v2.
Error model
400invalid request or schema violation.404referenced input/program/params not found.409conflict in post-run side effects (e.g. cursor/update conflicts).422run completed but business policy failed (reserved for policy checks).500internal failure.
Error payload:
{
"error": {
"code": "invalid_input_ref",
"message": "input ref not found",
"retryable": false
}
}
Behavioral differences from v1
- Removed write path: direct
POST /artifacts. - New requirement: every write returns a receipt ref tied to a PEL run.
pel/runsemantics become the write gateway rather than an optional compute endpoint.
Compatibility and rollout
- Add
/v2/pel/executewhile keeping/v1/*unchanged. - Mirror core read endpoints under
/v2/*. - Mark
POST /v1/artifactsas deprecated in docs. - Migrate clients to v2 execute flow.
- Remove v1 write endpoints in a later major release.
Open questions
- Should v2 require exactly one output for write operations, or allow multiple outputs with one receipt?
- Should inline artifact body support both
body_hexandbody_base64, or move to multipart for large payloads? - Should
publish_outputsdefault totrueor be explicit-only? - Do we need async execution (
202 + run status endpoint) for long-running programs in v2?
Minimal implementation plan
- Add v2 contract bytes (
registry/amduatd-api-contract.v2.json). - Add
/v2/pel/executehandler by adapting existingPOST /v1/pel/run+ artifact ingest path. - Factor shared receipt parsing/building from current v1 pel handler.
- Add tests:
- inline artifact -> stored -> run -> receipt success,
- failure before run,
- failure during run,
- side effect gating (no publish on failure).
- Document deprecation notice for
POST /v1/artifacts.