v1 of an ic-query minor slice, if anybody cares to provide feedback
# ic-query 0.26 Design: SNS Maturity Reward Evidence
## Status
- Status: planned for 0.26.0
- Last reviewed: 2026-08-02
- Scope: read-only SNS neuron permission evidence, maturity checkpoints, and
local reward deltas
## Goal
Support SNS DAOs that use Governance maturity as a non-inflationary measure of
reward entitlement. The new surface must let an operator prove whether
maturity conversion is disabled by the effective permission state, collect a
complete reward-round-aligned maturity checkpoint, and compare two checkpoints
without enumerating proposal ballots.
The slice remains reporting-only. It does not sign identities, call
`manage_neuron`, submit proposals, alter permissions, reset maturity, transfer
revenue, or generate JavaScript for execution in another application’s browser
context.
## Protocol Facts And Policy
SNS Governance currently defines these neuron permission codes:
| Code | Permission |
| —: | — |
| 0 | `Unspecified` |
| 1 | `ConfigureDissolveState` |
| 2 | `ManagePrincipals` |
| 3 | `SubmitProposal` |
| 4 | `Vote` |
| 5 | `Disburse` |
| 6 | `Split` |
| 7 | `MergeMaturity` |
| 8 | `DisburseMaturity` |
| 9 | `StakeMaturity` |
| 10 | `ManageVotingPermission` |
Codes 7, 8, and 9 are the prohibited maturity-conversion permissions for this
design. A checkpoint satisfies the global non-inflation policy only when:
- `neuron_claimer_permissions` excludes 7, 8, and 9;
- `neuron_grantable_permissions` excludes 7, 8, and 9;
- every current principal permission entry on every neuron excludes 7, 8, and
9; and
- every neuron has an empty pending maturity-disbursement collection.
The first two checks govern new claims and future grants. They do not revoke a
permission already held by a principal, so a parameter-only audit is not
sufficient for an existing SNS. The full paged neuron collection is required.
`ManagePrincipals`, `Vote`, and `SubmitProposal` are required claimer
permissions in the current Governance implementation. Whether
`ManagePrincipals` should be grantable to another principal is a separate
control-transfer policy. The report exposes that fact as a warning but does not
classify it as maturity inflation.
Governance authorizes `ChangeAutoStakeMaturity` through
`ConfigureDissolveState`, not `StakeMaturity`. Reward distribution adds new
maturity to staked maturity when auto-stake is enabled and to unstaked maturity
otherwise. The stable reward score for one neuron is therefore:
```text
reward_score_e8s_equivalent =
maturity_e8s_equivalent
+ staked_maturity_e8s_equivalent.unwrap_or(0)
```
Changing auto-stake moves future accrual between those components and does not
invalidate the combined score. A pending maturity disbursement is preserved as
separate evidence and makes the checkpoint ineligible; it is not silently
added back into the payout score.
There is no native operation that resets maturity to zero as pure accounting.
Merge, stake, and disburse operations consume or reclassify maturity and can
eventually create additional SNS-token stake or liquid supply. This design uses
immutable checkpoint deltas instead of reset behavior.
## Existing Surface And Hard Boundary
The schema-2 `SnsNeuronRow` continues to represent the fixed-size fields used
by normal bounded lists and complete neuron caches. It is not expanded with
permissions, followees, or pending disbursements, and the existing neuron cache
schema does not advance in this slice.
The reward workflow uses a separate explicit row and report because it needs
variable-size permission and pending-disbursement evidence. This preserves the
0.25 rule that ordinary `sns neuron list` and `sns neuron refresh` do not grow
their response, cache, or rendering contract implicitly.
## CLI Surface
The intended command surface is:
```bash
icq sns neuron info <id|root-principal>
icq sns reward checkpoint <id|root-principal>
icq sns reward diff <before-checkpoint.json> <after-checkpoint.json>
```
All live commands accept the existing explicit SNS source endpoint and global
mainnet network identity. Text is a human-facing summary. `–json` retains raw
permission codes, principals, maturity values, event fields, timestamps, and
policy findings.
`reward diff` is local-only. It must reject network and source-endpoint options
rather than accepting an option that appears capable of making a live call.
## Neuron Detail
`sns neuron info` calls native Governance `get_neuron` for one exact neuron id.
It preserves:
- every principal and raw permission code, with a derived current permission
name when known;
- unstaked and staked maturity;
- the auto-stake setting;
- pending maturity disbursements, including raw amount and timestamps;
- fixed-size neuron state already represented by `SnsNeuronRow`; and
- legacy and topic followees as native detail evidence.
Unknown future permission codes remain visible and receive an `unknown` label.
Missing principals and malformed ids remain typed source-data failures. The
report is live-only and does not read or write the complete neuron cache.
Including targeted discovery, one detail report makes three client queries:
one SNS-W inventory query, one selected-SNS metadata query, and one Governance
`get_neuron` query. SNS neurons are publicly readable under the current native
contract, so the built-in source remains anonymous and does not introduce
identity-file handling.
## Reward Checkpoint Collection
`sns reward checkpoint` performs this ordered collection:
1. resolve exactly one deployed SNS through targeted discovery;
2. read Governance nervous-system parameters;
3. read `get_latest_reward_event`;
4. exhaust `list_neurons` with the native maximum page size of 100;
5. read nervous-system parameters again; and
6. read `get_latest_reward_event` again.
For `N` neuron pages, this makes `N + 6` client queries including targeted
discovery. It does not call `get_proposal`, enumerate ballots, fan out with one
`get_neuron` call per row, query a ledger, or inspect transaction history.
The before and after parameter responses must agree on the claimer and
grantable permission lists. The before and after reward events must identify
the same reward round, event timestamp, and distributed amount. A mismatch is
a typed unstable-checkpoint failure; no successful checkpoint is emitted.
An optional diagnostic page cap may stop collection, but capped collection is
incomplete and cannot produce a checkpoint. Page cursors, row uniqueness, SNS
identity, and API exhaustion follow the existing complete neuron refresh
validation rules.
Each checkpoint row contains:
- neuron id and creation timestamp;
- unstaked, staked, and combined maturity;
- auto-stake state;
- every current principal permission entry;
- every pending maturity disbursement; and
- row-level policy findings.
The checkpoint summary contains the full parameter permission lists, both
bracketing reward-event responses, page and row counts, collection start and
end timestamps, aggregate maturity totals, policy finding counts, and an
overall `non_inflationary_policy_satisfied` boolean.
The report always states `point_in_time_guaranteed: false`. Stable bracketing
proves that the observed reward round and relevant global parameters did not
change during the walk. Governance exposes no collection version proving that
all neuron rows came from one instant, and principals may still change neuron
state between pages.
## Checkpoint Publication
The first slice does not add another implicit cache or overwrite the existing
complete neuron snapshot. A checkpoint is a versioned report emitted to stdout;
an operator persists JSON explicitly, for example:
```bash
icq sns reward checkpoint 1 --json > reward-checkpoint-42.json
```
This keeps history retention, filesystem naming, and backup policy visible to
the caller. A later append-only checkpoint store must define collision,
retention, and content-integrity behavior before writing beneath the shared
cache root.
## Local Reward Diff
`sns reward diff` strictly loads two current checkpoint schemas and requires
matching network, Root principal, Governance principal, and SNS identity. The
after checkpoint must have a later reward-event position than the before
checkpoint. Both checkpoints must have completed collection and satisfied the
non-inflationary policy.
Rows are joined by full neuron id. For each row:
```text
reward_delta_e8s_equivalent =
after.reward_score_e8s_equivalent
- before.reward_score_e8s_equivalent
```
The diff preserves raw integer values and reports:
- positive, zero, and negative deltas;
- neurons created after the earlier checkpoint, using zero as their earlier
score only when the timestamps support that classification;
- neurons missing from the later checkpoint;
- permission or pending-disbursement policy changes; and
- the total positive delta used as the allocation denominator.
A negative delta, unexplained missing neuron, target mismatch, policy failure,
or arithmetic overflow makes the allocation invalid. It remains visible as
typed evidence rather than being clamped to zero.
The report produces per-neuron integer numerator weights and a shared integer
denominator. It does not infer a beneficiary or transfer account. An SNS neuron
may contain several principals, and its permission list does not define one
canonical owner. A payout system must use a separately authenticated beneficiary
registry or a claim mechanism.
## Permission Remediation And Operational Sequence
For a new SNS, operators configure both claimer and grantable permission lists
without codes 7, 8, and 9 before neurons are claimed.
For an existing SNS, the safe sequence is external to `ic-query`:
1. adopt the parameter change that removes 7, 8, and 9 from future claimer and
grantable permissions;
2. have authorized users remove 7, 8, and 9 from every current principal entry
on every neuron;
3. wait for every already-pending maturity disbursement to finalize;
4. use a complete checkpoint to prove the policy and establish the baseline;
5. collect another checkpoint after a later settled reward round; and
6. use the local diff as input to an independently authorized revenue payout
process.
Changing global grantability prevents removed maturity permissions from being
granted again under the current parameters, but a later Governance proposal
can change those parameters. Every checkpoint therefore repeats the global and
per-neuron audit.
Permission removal itself is intentionally not automated here. Native
Governance permits a caller with `ManagePrincipals` to remove its own
permissions and even to remove the last permission entry, permanently locking
the neuron. An identity-aware wallet or frontend should render the exact
`RemoveNeuronPermissions` request, require informed confirmation, and protect
the last `ManagePrincipals` holder. `ic-query` reports the before and after
state only.
## Public Library Boundaries
- `SnsNeuronSource` owns one exact native detail lookup.
- `SnsRewardSource` owns nervous-system parameters, latest reward event, and
paged reward-neuron collection for one resolved SNS.
- `SnsNeuronDetailReport`, `SnsRewardCheckpointReport`,
`SnsRewardCheckpointRow`, permission and pending-disbursement DTOs, and
`SnsRewardDiffReport` remain usable without default features.
- Live builders, local checkpoint loading, and source traits remain behind
`host`.
- Report builders validate custom-source evidence with the same target,
ordering, bracketing, permission, and arithmetic rules as the built-in
adapter.
Reusable permission-code decoding belongs in the SNS report module. CLI
parsing and dispatch remain in `ic-query-cli`; network calls, report assembly,
local checkpoint reads, and rendering remain in the SNS report owners.
## Validation And Tests
Focused fixture tests cover:
- every known permission code and an unknown future code;
- prohibited claimer, grantable, and current-principal permissions;
- pending maturity disbursements;
- auto-staked and unstaked combined maturity;
- reward-event and parameter changes across a paged walk;
- duplicate, overlapping, malformed, capped, and non-exhausted pages;
- valid new-neuron deltas, negative deltas, and missing neurons;
- checkpoint schema, target, network, and event-order mismatches;
- exact integer aggregate and denominator arithmetic; and
- local-only diff behavior with no live source calls.
Unit tests use fixture sources and temporary files. No test depends on a live
SNS, an identity, a signed update, or exact full human-readable output unless
that text is the command contract.
## Non-Goals
- signed `manage_neuron` calls or identity storage;
- proposal submission or parameter mutation;
- browser-console jailbreak scripts;
- maturity reset, burn, merge, stake, or disbursement;
- treasury transfers or automatic payouts;
- beneficiary inference from neuron permissions;
- proposal-ballot collection; and
- a claim or Merkle-distribution canister.
## Official Interfaces
- [SNS Governance Candid interface](https://github.com/dfinity/ic/blob/master/rs/sns/governance/canister/governance.did)
- [SNS Governance neuron and permission protobuf](https://github.com/dfinity/ic/blob/master/rs/sns/governance/proto/ic_sns_governance/pb/v1/governance.proto)
- [SNS Governance implementation](https://github.com/dfinity/ic/blob/master/rs/sns/governance/src/governance.rs)
- [SNS settings](https://docs.internetcomputer.org/references/sns-settings/)
- [SNS neurons](https://learn.internetcomputer.org/hc/en-us/articles/34084687583252-Neurons)