Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 38 additions & 13 deletions web4-standard/core-spec/presence-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ This protocol is versioned with a single integer `protocolVersion`.
change to error code semantics, requires a version bump.**

The daemon advertises its `protocolVersion` in the
[`tool/connect`](#31-tool-connect) response. SDKs MUST expose a
[`hestia_connect`](#31-hestia_connect) response. SDKs MUST expose a
`PROTOCOL_VERSION` constant matching the version they implement.
SDKs SHOULD emit a warning on connect if their version differs
from the daemon's; they SHOULD NOT refuse the session — forward
Expand All @@ -97,10 +97,19 @@ via content negotiation, but this is not required for v0.

## 3. Tool surface

All tool calls follow standard MCP JSON-RPC semantics. The wire
format for tool input arguments is **camelCase** JSON; tool output
is also camelCase. Timestamps are ISO-8601 UTC strings. UUIDs are
RFC 4122 v4 hex with dashes. Session IDs are UUIDs.
All tool calls follow standard MCP JSON-RPC semantics. Wire casing
is split by surface and is fixed by the JSON Schemas in
`web4-standard/schemas/presence-protocol/` (normative — see §7):

- **Tool input arguments are `snake_case`** (`plugin_id`,
`host_agent`, `action_id`, …), as the input schemas require.
- **Tool output and all §5 type-catalog shapes are `camelCase`**
(`sessionId`, `softLct`, `protocolVersion`, …).
- **§4 resource bodies are `snake_case`** (`sovereign_lct`,
`chain_length`, …), matching the bound conformance vectors.

Timestamps are ISO-8601 UTC strings. UUIDs are RFC 4122 v4 hex
with dashes. Session IDs are UUIDs.

The eight tools below MUST be implemented by a conforming
presence layer.
Expand Down Expand Up @@ -139,12 +148,12 @@ same plugin_id as synthetic for the lifetime of that record.
"sessionId": "97a3-...",
"softLct": "lct:web4:session:abc123",
"assignedRole": "citizen",
"protocolVersion": 0
"protocolVersion": 1
}
```

**Errors:**
- `hestia.invalid_role` — the requested role is not available to plugins
- `hestia.invalid_role` (v1+) — the requested role is not available to plugins; v0 daemons MAY emit `hestia.internal_error` instead (see §6.1)
- `hestia.internal_error` — connection setup failed

### 3.2 `hestia_begin_action`
Expand Down Expand Up @@ -426,9 +435,12 @@ All resource bodies are JSON, mime type `application/json`.

## 5. Type catalog

All wire shapes use **camelCase keys** regardless of the source
language's native convention. Languages map to their native casing
via serializer hints.
The type-catalog shapes below — and all tool **output** shapes —
use **camelCase keys** regardless of the source language's native
convention. Languages map to their native casing via serializer
hints. This camelCase rule does **not** extend to tool *input*
arguments or §4 resource bodies, both of which are `snake_case`
per §3 and the bound schemas/vectors.

### 5.1 Session

Expand Down Expand Up @@ -481,12 +493,18 @@ via serializer hints.
"policy:policy:<hex>",
"decision:deny",
"rule:deny-destructive-commands"
]
],
"status": "decided",
"nextPollMs": null
}
```
`decision` is one of `"allow"`, `"deny"`, `"warn"`. `ruleId` and
`ruleName` are `null` on default-policy decisions. `policyId` is
the v0 alias of `ruleId` retained for back-compat.
the v0 alias of `ruleId` retained for back-compat. `enforced` is
`true` when the policy engine actively blocked or allowed the
action (vs. a default pass-through). `status` and `nextPollMs`
support the wait protocol (§3.4.1): synchronous engines always
return `"decided"` / `null`.

### 5.5 TrustState

Expand Down Expand Up @@ -610,6 +628,13 @@ A conforming SDK implementation MUST:
present in tool results.
4. Pass the conformance test scenarios against a reference daemon.

**Precedence.** Where this document's prose and the JSON Schemas
at `web4-standard/schemas/presence-protocol/` (or the conformance
vectors bound in item 5) disagree about a wire shape — including
key casing — the Schemas and vectors are normative and the prose
is in error. The Schemas directory is normatively bound by this
clause, not only the vectors JSON.

Conformance does not require implementing the v0 policy engine
stub literally; an implementation MAY return real policy
decisions earlier than the spec mandates, provided the shape
Expand All @@ -628,7 +653,7 @@ honesty about where it isn't yet held.
| `TrustState` is missing `entityId`, `successCount`, `successRate` in all SDKs | All 3 SDKs | Add fields — covered by `1a-4`. |
| Error codes `policy_denied`, `vault_denied`, `invalid_role` referenced by SDKs but never emitted by daemon | Daemon | Emit them when the policy engine lands in v1. |
| `WitnessEntry.timestamp` is a string in SDK types but parsed as `chrono::DateTime` in Rust | Rust SDK | Internal — wire format is the string. No spec change. |
| Daemon's `hestia://society/state` resource returns `trust_states_known` (snake_case) | Daemon | Rename to `trustStatesKnown` for camelCase consistency in v1. |
| Daemon's `hestia://society/state` resource returns `trust_states_known` (snake_case) | None — not drift | §3/§4.1 fix `snake_case` as the normative casing for resource bodies, consistent with the §7-bound conformance vectors (`sovereign_lct`, `chain_length`, …). No rename: the earlier camelCase aspiration contradicted the bound vectors. |

---

Expand Down