Part of Stem. This page defines the policy kind. The sync protocol is driven by explicit policy, and this is where the policy lives: as a resource, so it is signed, versioned, inspectable and shared between an account's devices by the same sync it governs. The formal schema of this kind's state is attached as the schemaDefinition of this page.
Descriptor
{
"name": "Sync policy",
"description": "An account's rules for what to follow, pin, fetch on demand or ignore.",
"state": "snapshot",
"schema": "hm://z6MkiAKDcRSzQ4zPZfnJcS5HYx5MwgN6MU9foHihJGrhqNBj/stem/kinds/policy/value",
"naming": "named",
"children": false,
"access": "own",
"retention": "latest",
"links": []
}State
field | type | required | meaning |
|---|---|---|---|
| list of policy-rule | yes | The rules, evaluated most specific scope first. |
Each rule names a scope, a mode (follow, pin, on-demand, ignore), optional extra peers and an optional interval. The semantics of the modes are on the policy-rule page and in The sync protocol.
Rules
The policy is a node of kind policy in the account's own space, placed directly under the root with the name policy. A daemon finds it by that name, since node ids are CIDs and cannot be fixed in advance. An account may keep several policy nodes under other names, and the daemon merges them, most specific scope first.
Access is own with no grants: the readers are the owner alone. A device that authenticates as the account reads it; nobody else does, and the policy is excluded from every public scope set. This is what "only the account's devices receive it" means; no grant is needed.
Only a key with write on the account's root may publish a policy. Devices of the account have this through the account key or a write grant to the device key.
A daemon holding keys for several accounts applies the union of their policies. A conflict between accounts on the same scope resolves to the most permissive mode except ignore, which always wins for the account that set it.
Rules are the only standing interest a daemon has. Opening a resource in a client marks its scope hot for a short while through Sync; only a rule makes the daemon keep coming back.
A site daemon's policy is written by its operator through SetPolicy under the site's own account key, typically one pin rule per published space.
Retention is latest. Old policies are not interesting to keep.
Today (HM24)
Standing interest was a local subscriptions table of (iri, recursive) rows that never left the device, plus the desktop app's own polling of DiscoverEntity for whatever was on screen, plus contacts that the apps turned into subscriptions (Network). There was no way to say "never accept this", "keep this offline" or "fetch only on request", and no way for a second device to see the first one's choices. The roadmap decided to remove subscriptions as a user-facing concept; the policy resource is what replaces them.
Example
{
"type": "Snapshot",
"signer": { "/": { "bytes": "7QFo…" } },
"sig": { "/": { "bytes": "…" } },
"ts": 1759906000000,
"schema": "hm://z6MkiAKDcRSzQ4zPZfnJcS5HYx5MwgN6MU9foHihJGrhqNBj/stem/kinds/policy/value",
"value": {
"rules": [
{ "scope": { "space": { "/": { "bytes": "7QFo…" } }, "depth": "subtree" }, "mode": "pin" },
{ "scope": { "space": { "/": { "bytes": "7QHm…" } }, "depth": "subtree" }, "mode": "follow", "interval": 60 },
{ "scope": { "space": { "/": { "bytes": "7QHm…" } }, "node": "bafyrein7o4v43impflvfupxqmb2y2nyrvd7rxinfrpyz43tbic367aez54", "depth": "subtree", "facets": ["state", "files"] }, "mode": "pin" },
{ "scope": { "space": { "/": { "bytes": "7QZz…" } }, "depth": "subtree" }, "mode": "ignore" }
]
}
}The first rule pins the account's own space. The second follows the Starlight space with a one-minute interval. The third pins one folder of it, content and files only, for offline use. The fourth refuses anything from a space the account wants nothing from, even if offered.
The Node blob of the policy resource, an update of an existing policy node (so it carries id), named policy under the root:
{
"type": "Node",
"signer": { "/": { "bytes": "7QFo…" } },
"sig": { "/": { "bytes": "…" } },
"ts": 1759906000000,
"id": "bafyreisqxezyex3rdrgdsjpr3umx3bznfd24is7dik62vstqqzpt6zhkke",
"kind": "hm://z6MkiAKDcRSzQ4zPZfnJcS5HYx5MwgN6MU9foHihJGrhqNBj/stem/kinds/policy",
"parent": "bafyreiujzdegxdncf32epf3dhodzdocis2jhtlgmxgedn73u55xtplpft7",
"name": "policy",
"target": { "kind": "snapshot", "snapshot": { "/": "bafy2bzacen…" } },
"access": "own"
}See also
The sync protocol: how rules drive reconciliation, watching and retention.
Do you like what you are reading? Subscribe to receive updates.
Unsubscribe anytime