layer must authenticate callers and enforce current access-engine authorization
before invoking it. Supplying a tenant string is not an access grant. No route
or runtime configuration exposes these operations in this increment.
## Commands and reads
| Method | Contract |
| --- | --- |
| `register(context, memo, key=...)` | Version 1, no approval binding or seal; rejects ids already present in the memo store; returns durable event id |
| `revise(context, memo, expected_version=..., summary=..., key=...)` | Exact current revision precondition and next version; nonempty change summary; returns durable event id |
| `annotate(context, memo_id, version, kind=..., body=..., key=...)` | Append source/evaluation/comment to an existing exact revision; returns durable event id |
| `retrieve(tenant, memo_id, version=None)` | Retrieve current or historical memo only within its registered tenant |
| `events(tenant, memo_id, after=0, limit=100)` | Ordered cursor page of attributed immutable events, maximum 100 |
Registration returns the memo's existing caller-supplied id through retrieval;
generated public ids and canonical URLs are deferred to the API adapter. Memo ids
remain globally unique because existing review URLs and storage use that key.
An existing imported memo cannot be taken over by registration, even if its bytes
match. A tenant mismatch produces the same unavailable error as a missing record.
This is partition enforcement, not a replacement for per-record authorization.
Idempotency scope is tenant + actor kind/subject + operation + key. A SHA-256 of
canonical command JSON detects content conflicts, including changed revision
preconditions. Exact retries return the original event id even after subsequent
revisions. Different authors must use concurrency preconditions; matching content
alone never makes a stale edit succeed. The command bound is 256 KiB.
All writes use one SQLite transaction for memo content, immutable lifecycle event,
pending-delivery row and idempotency receipt. An event queue failure rolls back
the content mutation. Events contain actor, tenant, server timestamp, record and
revision; they do not record an authorization verdict or approval validity.
## Companion records
* Comment: `text`, optional `locator`. This is discussion, not a disposition.