Local account and quota ledger¶
synapse entitlements stores account and quota evidence in a separate owner-only
SQLite ledger at $XDG_STATE_HOME/synapse-channel/entitlements/ledger.sqlite3
(normally ~/.local/state/synapse-channel/entitlements/ledger.sqlite3). It does not write account names or
balances to the shared hub event log. The one exception is a pool the owner
explicitly advertises (see below), and only in redacted form. The show and history commands are
local owner operations. A registered MCP read tool exposes only the count of
accounts and pools; it withholds identities, labels, products, balances, sources
and credential references. Neither view grants spending or routing authority.
Record evidence¶
Write one JSON event to an owner-only file (mode 0600 on POSIX), then run:
synapse entitlements record --file account.json
synapse entitlements show
synapse entitlements history
The input must contain event_id, kind, recorded_at, source and
confidence. recorded_at and all other times require an explicit UTC offset;
quota windows use half-open [starts_at, ends_at) boundaries. Confidence is
official, operator or inferred; it is provenance, not a guarantee that a
vendor's current balance is known. The JSON field set is strict. Every quantity
is a finite, non-negative decimal string in the pool's declared unit.
Currency, token, percentage and call units remain separate pools and are never
added into a combined balance. Product surfaces (Chat, coding CLI and API) are
separate unless an operator has evidence that they genuinely draw from the same
pool. Never place a password or token in an event. The optional credential_ref
is a reference to existing secret handling and must start with ref:.
An account event creates an opaque account id, a private label and status
(active, suspended or expired). A pool belongs to one account and declares
one unit. A surface belongs to the pool and account. A window declares one
grant, unit, price revision and bounded time interval. Usage and balance
observations refer to both a window id and the exact window event revision.
Their source_event_id must be unique within that pool window. The same
underlying transaction seen through two product surfaces is recorded once
at the pool window. Replaying the same event id with identical content does
nothing; reusing it for different content is refused.
For example, an operator can enter an account event:
{
"event_id": "account-entry-1",
"kind": "account",
"recorded_at": "2026-09-19T10:00:00+02:00",
"source": "operator:billing-owner",
"confidence": "operator",
"account_id": "account-opaque-1",
"label": "My private coding account",
"status": "active"
}
Then create its pool, surfaces and window before adding observations:
kind |
Required fields beyond the common fields | Optional fields |
|---|---|---|
account |
account_id, label, status |
credential_ref, expires_at |
pool |
pool_id, account_id, unit |
— |
surface |
surface_id, account_id, pool_id, product, channel |
— |
window |
window_id, pool_id, starts_at, ends_at, grant, unit, price_revision |
renewal_at |
usage |
window_id, window_event_id, source_event_id, amount, observed_at |
— |
balance |
window_id, window_event_id, source_event_id, remaining, observed_at |
— |
balance.remaining may be null to express a missing provider balance. The
common optional field is supersedes for an explicit correction. Invalid
references, overlapping windows and mismatched units are refused. CLI
--store PATH can select another private ledger, whose parent directory must
be owner-only.
Import local Ollama token telemetry¶
Ollama's generate and
chat APIs expose prompt_eval_count and
eval_count in the final response. Capture one response with stream: false
in an owner-only JSON file, after creating a tokens pool and a window that
covers its created_at time. Then run:
synapse entitlements observe-ollama --file ollama-response.json \
--window-id my-window --window-event-id my-window-revision
The command imports the sum of input and output token counts as one usage observation. It stores a hash of the exact response as its source identity, so reimporting the file is idempotent. It does not store the response text, prompt, messages, reasoning or tool calls. Keep the captured input file private and remove it under your own retention policy. A partial stream, missing count, negative count, invalid timestamp or wrong window is refused. These are local model usage counts, not a vendor quota or price; the operator must supply any grant and must verify that the source belongs to the chosen pool.
Correct facts without erasing history¶
To correct a fact, submit another event with a new event_id, later
recorded_at, the same logical target and supersedes set to the prior event
id. history retains both records and their distinct sources. A corrected
window carries a new event revision; old balance samples remain in history but
do not contribute to a forecast for the new price or reset revision. New quota
periods use a new, non-overlapping window id.
Interpret the report¶
show reports per-pool windows and surfaces. A remaining value derived only
from recorded usage is labelled incomplete_usage_estimate; it is not a vendor
balance. A missing latest balance is unknown. Suspended or expired accounts
have account_usable=false. Forecasts require at least three current-revision
balance observations covering an hour. The report includes sample count,
observation age, confidence and a reason when data are insufficient, stale,
quiet, replenished or changed. A burst can lower confidence. The forecast is
advisory and never acts as a reservation or hard spend limit.
The ledger is local to one owner. Cross-hub reservations, authoritative distributed limits and federated projections require Fleet's separate admission and review gates. Operator-entered vendor figures must be refreshed from current official evidence; Synapse does not infer plan allowances or prices from product names.
Compute credits and approved work¶
A pool may declare resource_kind as gpu_time (gpu_seconds),
quantum_shots (shots), quantum_credits (quantum_credits), ci_minutes
(ci_minutes) or cloud_grant (USD, CHF or EUR). A classified pool must
also declare non-empty capabilities, data_classes and eligible_projects
lists. They are exact identifiers, so restricted data or another project
cannot borrow a general pool by name similarity. An optional idle_cost
object has amount_per_hour as a decimal string and currency as USD, CHF or
EUR. It is an operator-supplied rate, shown separately from quota remaining;
Synapse does not invent a charge or add currencies. The account's existing
active/suspended/expired status still governs pool usability.
Use a new non-overlapping window for each recurring grant/reset. Its ends_at
is the grant expiry. show reports expires_in_seconds and an
upcoming_expiry flag for current windows ending within seven days; expired
windows have no usable remaining balance. Usage and manual balance corrections
retain their source events and exact window revision. A suggestion requires a
known, recent balance and subtracts later recorded usage; a usage-only
estimate never authorises a suggestion. Unit types are never converted or
summed together.
To request advisory matching, put at most 128 candidate work specifications in
an owner-only JSON file of the form {"tasks": [...]}. Each task needs the
exact task_id, project, resource_kind, capability, data_class, unit,
positive required_amount, estimated_total_cost, max_total_cost,
cost_currency, price_revision, integer priority (1–5), the current
board_version and
authorisation_expires_at. Amounts and costs are decimal strings. The cost
estimate is operator evidence, not a provider quote. Its approved maximum must
cover the estimate. For each task, obtain the exact digest-bound approval
subject and route it through the existing hub approval workflow:
synapse entitlements compute-subjects --file private-tasks.json
synapse approval request --name PROJECT/seat --subject compute-credit:SHA256
synapse approval decide --name REVIEWER/seat --subject compute-credit:SHA256 --approve
synapse entitlements suggest-compute --file private-tasks.json \
--hub-db /path/to/hub.db --reviewer REVIEWER/seat
The task must already exist on the same hub board as an open, dependency-ready
task with matching project and version. The subject includes every task field,
including its data class, required amount, full cost ceiling, board version,
price revision and authorisation expiry. A changed
file needs a new approval. The selected reviewer identity must match the
latest approved hub decision. Local suggestions refuse stale account or
balance evidence (default maximum age seven days), suspended/expired accounts,
expired grants, missing or old approvals, wrong project/data/capability, price
revision mismatch, insufficient remaining units and cost over the approved
limit. --max-evidence-age-hours can tighten the age bound. Every refusal is
shown as an excluded task; matching pool/window options show their own unit,
expiry and separately declared idle rate.
This is an owner-only advisory read. An approval note is audit evidence, not a provider authorisation token. The command does not reserve a grant, activate a billing account, buy capacity, launch a job or change the hub task state. Fleet F08 owns any later authorised provider lifecycle.
Advertise a pool to fleet planners¶
A fleet that plans work across hubs needs to know which pools exist and roughly
how much is left. synapse entitlements advertise --pool POOL_ID --alias ALIAS
shares one pool, by the owner's choice only, in redacted form. --dry-run
prints exactly what would be sent.
What the advertisement shares:
- the alias, never the pool id, account id, account label, credential
reference, products or source references;
- the unit, the resource kind, and the capabilities, data classes and eligible
projects the planner needs to rule out unsuitable work;
- per window, an opaque reference, the end time and whether the window is
current;
- a remaining-balance bucket per window (>50%, 10-50%, <10%,
depleted or unknown), never the amount;
- the class of balance evidence, the age of the last observation, the forecast
state and the confidence.
What the hub requires:
- a durable journal (--db);
- a cryptographically proven sender;
- the entitlement-advertise ACL grant for the alias (target kind
pool-alias), which is always enforced.
The advertisement becomes an audit-only journal row with the advertiser and the hub id. It is never broadcast to connected seats. Operators and fleet mirrors read it from the journal, so a seat without journal access cannot see it. Advertising again records a newer row; nothing is removed.