Skip to content

Operations

Operations are Ramose’s only public write path. They turn product verbs—create task, close issue, invite member—into stable, typed capabilities that the application and MCP endpoint can both invoke.

An entity- or trait-owned operation has a permanent identity derived from its owner and local key. Task.setDone is different from another entity’s setDone. Targeted operations default to self: true; targetless operations set self: false and live on the database mutation namespace.

operations: (Operation) => ({
rename: Operation({
input: S.Struct({ title: S.String }),
output: S.Struct({}),
run(op, { title }) {
op.self.set(Task.title, title)
return {}
},
}),
})

The operation body receives a narrow writer. It may change its owner and explicitly declared related entities. The authoritative transaction applies defaults, fixed trait bindings, protected types, reference validation, and cascade rules before committing all or nothing.

A targeted invocation requires both an exact operation grant and visibility of a compatible target. A targetless invocation requires its exact grant. Readability never implies write permission; a grant never reveals a hidden target.

Hidden, missing, unauthorized, and wrong-type targets intentionally collapse to the same public rejection where distinguishing them would disclose data.

Optimism is a projection, not a second body

Section titled “Optimism is a projection, not a second body”

An operation may declare a pure optimistic projection. It receives validated input, stable client references, and a local transaction builder. It cannot query local state, inspect policy, read the clock, run Effects, or decide whether the operation is allowed.

Prefer requested target values such as { done: true } over basis-dependent commands such as toggle. That makes replay deterministic and lets rejection remove one optimistic layer before later layers are reapplied.

The client assigns every invocation a stable id before it becomes queued. The server stores a durable receipt scoped to principal, database, operation, target, and input. An identical retry returns the original result; reusing the id for another intent fails.

The browser exposes queued, committed, and rejected transitions. A lost acknowledgement, restart, reconnect, or leadership change across tabs cannot commit the same invocation twice.

Web app query · mutate · offline
One deployed model Schema · policy · operations authorization is applied before either caller sees data
Agent describe · query · mutate
The application and MCP endpoint are two doors into the same model, not two backends that must be kept aligned.

MCP mutate is only a generic adapter over these operations. Adding an operation adds a capability card; it does not add server glue or another MCP tool.