Gateway API
The browser and malt-client use the MALT Gateway at http://127.0.0.1:8080 by default. The gateway embeds the untrusted graph executor and owns ArcTable/KV/CAS persistence. It returns results and proofs; clients decide trust locally.
The current gateway tracks MALT v0.0.6. Normative resolve/read schemas remain in the MALT core repository.
Resolve and Read
POST /v1/resolve
POST /v1/readResolve accepts a caller-selected root and an array of application-produced segments:
{
"profile": "malt.resolve/v0alpha1",
"root": "<trusted MALT root>",
"segments": ["a", "b", "@payload"]
}It returns an untrusted target and ProofList. segments: [] means strict root identity. A resolver may group segments into authenticated arcs in more than one valid way; verification proves the returned derivation, not that it was longest or unique.
Read accepts one primitive typed query:
{
"profile": "malt.read/v0alpha1",
"root": "<typed map or list root>",
"query": {"kind": "map_key", "segments": ["account", "name"]}
}Other query kinds are list_index and list_range. Clients construct the expected request themselves and verify {request, result} locally with MALT core or the published WASM verifier.
Diagnostic Verification
POST /v1/verify/resolve
POST /v1/verify/readThese endpoints are for conformance and troubleshooting. Responses carry X-Malt-Verification-Role: diagnostic; they are not trust oracles and do not replace local verification.
CAS
POST /v1/cas?codec=<multicodec>
GET /v1/cas/{cid}
HEAD /v1/cas/{cid}POST accepts an immutable payload body up to 64 MiB and returns 201 Created with {"cid":"..."}. GET and HEAD return immutable bytes with CID-derived ETag and long-lived cache headers. Clients still hash returned bytes and compare them with the authenticated CID before use.
CAS stores payload bytes; it does not define MALT authentication semantics.
Create a Structure
POST /v1/rootsThe request contains a canonical arc map:
{
"arcs": {
"@payload": "<payload CID>",
"docs/readme.md": "<target CID>"
}
}The response is 201 Created with {"root":"<new root>"}. The returned root is an untrusted candidate until the caller explicitly accepts it or verifies an independent publication/transition policy.
Semantic Mutation Contract
POST /v1/roots/{root}/mutations{root} is the caller-selected base root. The request contains typed map/list deltas with canonical coordinate changes and optional replay constraints:
{
"deltas": [
{
"kind": "map",
"object": "<optional semantic-object CID>",
"changes": [
{
"path": "docs/readme.md",
"before": {"target": "<old CID>", "target_kind": "cas"},
"after": {"target": "<new CID>", "target_kind": "cas"}
}
]
}
]
}A successful mutation returns 201 Created with an operational receipt and a candidate new_root. MALT v0.0.6 does not provide a state-transition proof, so the Web App and malt-client never promote this root automatically.
Operator Root Publication
When GATEWAY_ADMIN_TOKEN is configured, the Gateway exposes bearer-protected managed-policy routes:
GET /admin/v1/scopes/{scope}/roots
POST /admin/v1/scopes/{scope}/roots
GET /admin/v1/scopes/{scope}/roots/{name}
POST /admin/v1/scopes/{scope}/roots/{name}/freezeA publish request is {"name":"main","root":"bafy..."}. Records carry a monotonic revision, previous root, timestamp, and optional frozen state. Freezing is irreversible. Publication does not modify ArcTable state, prove a mutation, choose the root of a request, or automatically update a client's accepted root.
Trust Boundary
The gateway may enforce access policy, cache results, orchestrate storage, and publish roots, but it is untrusted for correctness. Root freshness, rollback prevention, and multi-writer policy remain application or managed-service responsibilities.