docs: chaque symbole dit d'où il vient

98 annotations posées à côté des déclarations, et un test qui les exige sur la
surface publiée. Elles portent trois choses : le niveau qui répond, la référence
amont, et la catégorie parmi les cinq.

La cinquième est celle qui manquait : declared-not-wired, quand la cible DÉFINIT
la forme et ne la câble pas. Neuf symboles en relèvent, dont readLinks — que
j'avais classé « notre invention » en raisonnant depuis l'absence, alors que
c'est le meilleur alignement disponible.

Les références citent un SYMBOLE, jamais une ligne : trois citations du document
avaient déjà pourri. Cinq corrections au passage, toutes vérifiées à la source —
un chemin ORM qui n'existe pas, deux plages de lignes fausses, et surtout
docs.* et subscribeDoc étiquetés PASSTHROUGH alors qu'ils sont alignés : nos
noms, plus un argument jamais transmis. La sémantique survit à la migration,
les sites d'appel non, et la nuance disparaissait sous une étiquette trop
flatteuse.

Le test échoue à l'annotation retirée, à la catégorie mal orthographiée, et à
une invention qui prétendrait citer une référence — vérifié en cassant les
trois. Il a aussi attrapé un défaut en lui-même : le gabarit de format placé
dans index.ts se faisait analyser comme une annotation.

La classification couvre l'interne qui prétend ressembler à la cible — tout
emulated-verifier — et exclut ce qui ne le prétend pas. La faute d'origine
portait sur une fonction non exportée ; n'être pas publié n'a protégé personne.

Quatre symboles ont résisté et sont annotés avec leur catégorie dominante, la
seconde nommée dans la note plutôt que lissée.
This commit is contained in:
Sylvain Duchesne
2026-08-16 22:53:50 +02:00
parent 6138d831da
commit 43aadbeb45
26 changed files with 353 additions and 8 deletions
@@ -68,6 +68,7 @@ import type { InboxScope, Nuri, NuriLike, PrincipalId, ReadCap, Scope } from "..
* inbox read guard consults (`inbox.ts`). Anonymous holds no inbox, so it is false
* for everyone until an identity is set.
*/
// @provenance isOwnInbox kind=aligned level=1 ref=engine/repo/src/types.rs:AddInboxCapV0 — 'which inboxes may I read' is answered by the User branch's records
export async function isOwnInbox(nuri: Nuri): Promise<boolean> {
const holder = getCurrentUser();
if (holder === null) return false;
@@ -100,6 +101,7 @@ export async function isOwnInbox(nuri: Nuri): Promise<boolean> {
* not ours to hold. `id` is compared through the shim key, so it matches however
* the consumer spells the identity.
*/
// @provenance holdOwnCap kind=aligned level=1 ref=engine/repo/src/types.rs:AddRepoV0 — the cap of a document you created, filed on the store's Store branch. WIRED upstream — `send_add_repo_to_store` constructs it
export function holdOwnCap(id: string, scope: Scope, doc: Nuri, cap: ReadCap): void {
const holder = getCurrentUser();
if (holder === null || accountKey(holder) !== accountKey(id)) return;
@@ -124,6 +126,7 @@ export function holdOwnCap(id: string, scope: Scope, doc: Nuri, cap: ReadCap): v
* Scoped to the current holder, like {@link holdOwnCap}: another user's stores are
* emphatically not ours to hold.
*/
// @provenance fileOwnStructure kind=aligned level=1 ref=engine/verifier/src/site.rs:create_individual_ — a user's three stores are its own repos; it holds their caps by BEING a user
export function fileOwnStructure(id: string, record: VirtualUserRecord): void {
const holder = getCurrentUser();
if (holder === null || accountKey(holder) !== accountKey(id)) return;
@@ -135,6 +138,7 @@ export function fileOwnStructure(id: string, record: VirtualUserRecord): void {
/** Same, for the user's own inbox — it is its document, and it must be able to
* read it. Depositing into someone else's needs no cap (see `register-write.depositInto`). */
// @provenance fileOwnInbox kind=aligned level=1 ref=engine/repo/src/types.rs:AddInboxCapV0 — upstream the record IS the key (`priv_key`); here the cap is minted for the holder the record belongs to
export function fileOwnInbox(id: string, inbox: Nuri): void {
const holder = getCurrentUser();
if (holder === null || accountKey(holder) !== accountKey(id)) return;
@@ -160,6 +164,7 @@ export function fileOwnInbox(id: string, inbox: Nuri): void {
* did not: the address that WAS published is gone, and every future deposit on that
* document is refused as "this document has no inbox".
*/
// @provenance publishInboxAddress kind=divergent level=1 ref=engine/net/src/types.rs:ContactDetails — upstream an inbox address is TRANSMITTED (a message, a profile QR) and lands in the verifier's own per-user `inboxes` table; PUBLISHING it on the document is this library's deliberate divergence
export async function publishInboxAddress(doc: Nuri, inbox: Nuri): Promise<void> {
const s = await session();
try {
@@ -197,6 +202,7 @@ export async function publishInboxAddress(doc: Nuri, inbox: Nuri): Promise<void>
* its whole contract is that the connection either did the restore or says it did not.
* A caller that genuinely prefers to carry on catches it itself, and one of them does.
*/
// @provenance readStoreCaps kind=aligned level=1 ref=engine/repo/src/types.rs:AddRepoV0 — the replay of the Store branch — what reloads a store's documents with their keys
export async function readStoreCaps(storeDoc: Nuri): Promise<ReadCap[]> {
const s = await session();
const out: ReadCap[] = [];
@@ -246,6 +252,7 @@ export async function readStoreCaps(storeDoc: Nuri): Promise<ReadCap[]> {
* read. A failed READ is one, and it propagates — the caller is `connect.connectedUser`,
* whose contract is that it did the work or said it did not.
*/
// @provenance restoreOwnCaps kind=aligned level=1 ref=engine/verifier/src/verifier.rs:load_repo_from_read_cap — `AddRepo::verify` loads each repo from its read cap at replay; this is that replay, at connection
export async function restoreOwnCaps(holderKey: string): Promise<void> {
const holder = getCurrentUser();
if (holder === null) return;
@@ -294,6 +301,7 @@ export async function restoreOwnCaps(holderKey: string): Promise<void> {
* **Never creates.** Asking where to deposit must not bring an inbox into existence —
* only its owner opens one, and only on its own document.
*/
// @provenance documentInboxAddress kind=divergent level=1 ref=engine/net/src/types.rs:ContactDetails — the deposit-side half of the same divergence: upstream you are TOLD an address, you never read one off a document
export async function documentInboxAddress(doc: Nuri): Promise<Nuri | undefined> {
// RULE 2 — do not even attempt. Not holding the document, we have no address to
// find: upstream the inbox pubkey travels WITH what you can read, so "where do I
@@ -333,6 +341,7 @@ export async function documentInboxAddress(doc: Nuri): Promise<Nuri | undefined>
* place that records authorship. Holding a cap is NOT ownership: a cap can be
* received, and a recipient must not be able to open an inbox on what it merely reads.
*/
// @provenance ownsDocument kind=aligned level=1 ref=engine/repo/src/types.rs:AddRepoV0 — authorship is what the Store branch records; holding a cap is NOT ownership, since a cap can be received
export async function ownsDocument(doc: Nuri): Promise<boolean> {
const holder = getCurrentUser();
if (holder === null) return false;
@@ -381,6 +390,7 @@ function encodeInboxCap(doc: Nuri, inbox: Nuri): string {
* make a document's queue silently un-drained — a share that was delivered and never
* applied, with nothing to see anywhere.
*/
// @provenance readInboxCapPairs kind=declared-not-wired level=1 ref=engine/repo/src/types.rs:AddInboxCapV0 — the record is keyed by `repo_id` and `update_inbox_cap_v0` applies it with no is-store check — but the engine only ever commits one for the two STORE repos, never for a plain document
export async function readInboxCapPairs(): Promise<Array<{ doc: Nuri; inbox: Nuri }>> {
const holder = getCurrentUser();
if (holder === null) return [];
@@ -411,6 +421,7 @@ export async function readInboxCapPairs(): Promise<Array<{ doc: Nuri; inbox: Nur
}
/** The inbox recorded for one document, if this user opened one. */
// @provenance readInboxCapsFor kind=declared-not-wired level=1 ref=engine/repo/src/types.rs:AddInboxCapV0 — the per-document lookup over the same unwired record
export async function readInboxCapsFor(doc: Nuri): Promise<Nuri | undefined> {
return (await readInboxCapPairs()).find((p) => p.doc === doc)?.inbox;
}
@@ -437,6 +448,7 @@ export async function readInboxCapsFor(doc: Nuri): Promise<Nuri | undefined> {
* sign-in, on a document the application had never named, repeating at every connection
* because the record is durable. Reported live, three sign-ins out of three.
*/
// @provenance myInboxes kind=aligned level=1 ref=engine/repo/src/types.rs:AddInboxCapV0 — the User branch answers 'which inboxes may I read'. The document-inbox half of this list is declared-not-wired — see `readInboxCapPairs`
export async function myInboxes(): Promise<Nuri[]> {
const holder = getCurrentUser();
if (holder === null) return [];
@@ -473,6 +485,7 @@ export async function myInboxes(): Promise<Nuri[]> {
* wrong is not a near-miss: a Link filed under the wrong holder gives one user another's
* capability and leaves the real recipient with nothing.
*/
// @provenance addLink kind=declared-not-wired level=1 ref=engine/repo/src/types.rs:AddLinkV0 — the type is DEFINED and its `CommitVerifier::verify` is a no-op `Ok(())`; nothing in the engine constructs one
export async function addLink(cap: ReadCap, forHolder?: PrincipalId): Promise<void> {
const holder = forHolder ?? getCurrentUser();
if (holder === null) return;
@@ -525,6 +538,7 @@ function holderRing(forHolder: PrincipalId | undefined): string | undefined {
* `forHolder` names whose User branch is read when it is not the connected identity's —
* see {@link addLink}, whose idempotence check is the caller that needs it.
*/
// @provenance readLinks kind=declared-not-wired level=1 ref=engine/repo/src/types.rs:AddLinkV0 — same: defined, verifier is a no-op, constructed nowhere. NOT this library's invention — an absent implementation says nothing about the target
export async function readLinks(forHolder?: PrincipalId): Promise<ReadCap[]> {
const holder = forHolder ?? getCurrentUser();
if (holder === null) return [];
@@ -608,6 +622,7 @@ export async function readLinks(forHolder?: PrincipalId): Promise<ReadCap[]> {
* owner. To deposit into someone else's document, resolve
* {@link documentInboxAddress} and `inbox.post` into it.
*/
// @provenance storeRegistry.openDocumentInbox kind=declared-not-wired level=1 ref=engine/repo/src/types.rs:AddInboxCapV0 — every `Repo` carries `inbox: Option<PrivKey>` and the record is keyed by any `repo_id`, but `new_store_default` attaches one only to non-private STORES and `doc_create` leaves `inbox: None`. PUBLISHING the address is a separate, divergent act — see `publishInboxAddress`
export async function openDocumentInbox(docLike: NuriLike): Promise<Nuri> {
// Permissive in, precise out — see `model/nuri.ts`. Published through
// `surface/placement.ts`, so it is a door an application types against.
@@ -83,6 +83,7 @@ const STAND_IN_CAP = "OK";
* Build the cap-bearing form of `nuri` — `{target}:r:OK`. Passing an already
* cap-bearing reference yields the same value. INTERNAL to the emulated verifier.
*/
// @provenance mintCap kind=divergent level=1 ref=engine/repo/src/types.rs:readcap_nuri — upstream a cap is SERIALIZED from the ObjectRef at repo creation; here it is DERIVED from a NURI with a stand-in key. Unreachable from outside on purpose
export function mintCap(nuri: Nuri): ReadCap {
return `${targetOf(nuri)}${CAP_SEGMENT}${STAND_IN_CAP}`;
}
@@ -90,6 +91,7 @@ export function mintCap(nuri: Nuri): ReadCap {
/** The map key of the anonymous holder (no identity established yet). */
const ANONYMOUS = "";
// @provenance CapRegistry kind=aligned level=1 ref=engine/repo/src/repo.rs:Repo — the session's record of which repos it holds a `read_cap` for; upstream that record is the verifier's opened repos, never a queryable registry
export class CapRegistry {
/** holder → the caps they hold, indexed by the cap-less NURI. */
private heldByHolder = new Map<string, Map<Nuri, ReadCap>>();
@@ -126,6 +126,7 @@ const inFlight = new Map<string, Promise<void>>();
* Not fixed with a retry, a timeout or a flag on purpose: deciding *what to do* about a
* broker that cannot answer belongs to the caller, and it can only decide if it is told.
*/
// @provenance connectedUser kind=aligned level=1 ref=engine/verifier/src/verifier.rs:inbox — upstream the verifier restores and processes with nothing for a caller to await; this is the awaitable form, for a deterministic start
export async function connectedUser(): Promise<void> {
const holder = getCurrentUser();
if (holder === null) return;
@@ -223,6 +224,7 @@ export async function connectedUser(): Promise<void> {
* inherits it, failure included. That is what `ensureIdentity()` does, and it is the path
* on which the guarantee is published.
*/
// @provenance startConnect kind=aligned level=1 ref=engine/verifier/src/verifier.rs:inbox — the fire-and-forget form of the same — upstream no application asks for it at all
export function startConnect(): void {
void connectedUser().catch((error: unknown) => {
console.error(accessLogPrefix() + " connect failed:", error);
@@ -126,6 +126,7 @@ function fire(inbox: Nuri, process: () => Promise<void>): void {
*
* Idempotent inside the window: a second deposit into the same inbox joins the pending run.
*/
// @provenance scheduleInboxProcessing kind=divergent level=1 ref=engine/verifier/src/verifier.rs:inbox — upstream the RECIPIENT's own verifier applies its inbox; here another identity's session drains it on a timer. Deliberate, unpublished, and only possible on one shared wallet
export function scheduleInboxProcessing(inbox: Nuri, process: () => Promise<void>): void {
if (scheduled.has(inbox)) return;
const handle = setTimeout(() => fire(inbox, process), PROCESSING_DELAY_MS);
@@ -145,6 +146,7 @@ export function scheduleInboxProcessing(inbox: Nuri, process: () => Promise<void
* Resolves rather than rejects, like the timer path it stands in for: a drain's failure is
* reported where failures go, and a caller of this is not the party that asked for the work.
*/
// @provenance runScheduledInboxProcessingNow kind=divergent level=1 ref=engine/verifier/src/verifier.rs:inbox — the same drain, run at once; a test seam over the divergence above
export async function runScheduledInboxProcessingNow(): Promise<void> {
for (const [inbox, entry] of [...scheduled]) {
clearTimeout(entry.handle);
@@ -161,12 +163,14 @@ export async function runScheduledInboxProcessingNow(): Promise<void> {
* session that no longer exists. In-flight runs are not cancelled (nothing can un-issue a
* write already sent); they end where they end.
*/
// @provenance cancelScheduledInboxProcessing kind=divergent level=1 ref=engine/verifier/src/verifier.rs:inbox — cancels a pending drain — upstream there is no pending anything to cancel
export function cancelScheduledInboxProcessing(): void {
for (const entry of scheduled.values()) clearTimeout(entry.handle);
scheduled.clear();
}
/** Trace one completed drain — diagnostics, so gated by the access-log flag. */
// @provenance traceProcessed kind=invention level=none ref=none — a diagnostic line in this package's own log stream
export function traceProcessed(inbox: Nuri, holder: string, applied: number): void {
logStage(
"DEFERRED PROCESS " + shortNuri(inbox) + " for " + holder + " → " + applied + " link(s) applied",
@@ -29,6 +29,7 @@
* its reads. That is a deliberate reservation, not a hazard to guard against: the
* namespace names this library.
*/
// @provenance MACHINERY_NS kind=invention level=none ref=none — upstream a branch is a distinct CRDT with its own topic; a reserved subject prefix exists only because this library has no branches
export const MACHINERY_NS = "urn:ng-eventually:";
/**
@@ -37,6 +38,7 @@ export const MACHINERY_NS = "urn:ng-eventually:";
* Tolerant of `undefined` so a read path can hand it a possibly-absent binding
* without a preliminary check — an absent subject is not machinery.
*/
// @provenance isMachinerySubject kind=invention level=none ref=none — same — upstream nothing has to be filtered out of a document's own graph
export function isMachinerySubject(subject: string | undefined): boolean {
return subject !== undefined && subject.startsWith(MACHINERY_NS);
}
@@ -85,6 +85,7 @@ import type { Nuri } from "../model/types";
* - `"timed-out"` fallback fired without a `State` — open proceeded, sync UNconfirmed;
* `"unknown"` (from {@link getSyncState}) means "never requested / no `State` semantics".
*/
// @provenance SyncState kind=aligned level=1 ref=engine/net/src/app_protocol.rs:AppResponseV0 — the first `State` push IS the barrier; `timed-out` names the bounded fallback and is deliberately not `synced`
export type SyncState = "syncing" | "synced" | "timed-out";
/** Repos whose bootstrap open has completed (first `State` received OR timed out). */
@@ -114,12 +115,14 @@ let OPEN_TIMEOUT_MS = 8000;
* 8s production wait, too slow for a unit test. Production never calls this — the
* default stands. `resetOpenedRepos` restores the default.
*/
// @provenance setOpenTimeoutForTests kind=invention level=none ref=none — a test seam over the bounded fallback
export function setOpenTimeoutForTests(ms: number): void {
OPEN_TIMEOUT_MS = ms;
}
/** Reset the open registry (mainly for tests / a switched wallet). Tears down the
* held bootstrap subscriptions so a subsequent open re-subscribes cleanly. */
// @provenance resetOpenedRepos kind=invention level=none ref=none — per-session bookkeeping reset; upstream the verifier owns `self.repos` and nothing resets it from outside
export function resetOpenedRepos(): void {
for (const unsub of held.values()) {
try {
@@ -145,6 +148,7 @@ export function resetOpenedRepos(): void {
* `"timed-out"` (fallback fired without a `State`). `"synced"` and `"timed-out"`
* are deliberately distinct — a later readiness signal must not confuse them.
*/
// @provenance getSyncState kind=aligned level=1 ref=engine/net/src/app_protocol.rs:AppResponseV0 — reports whether the first `State` arrived; upstream this is not observable from JS
export function getSyncState(nuri: Nuri): SyncState | "unknown" {
return syncState.get(nuri) ?? "unknown";
}
@@ -184,6 +188,7 @@ async function syncSession(): Promise<void> {
* another holder would put a cap in the wrong ring, and a caller on that path has already
* established what its holder holds.
*/
// @provenance ensureRepoOpen kind=aligned level=2 ref=sdk/js/lib-wasm/src/lib.rs:doc_subscribe — a real subscription held for the session — upstream `doc_subscribe` is what brings a repo into `self.repos`, which `resolve_target_for_sparql` then requires
export async function ensureRepoOpen(nuri: Nuri, holderKey?: string): Promise<void> {
if (!nuri) return;
// A repo in a PUBLIC store hands its cap to whoever asks — upstream by serving it on
@@ -204,6 +209,7 @@ export async function ensureRepoOpen(nuri: Nuri, holderKey?: string): Promise<vo
* for nobody else; neither entry point re-exports it. The `Unguarded` suffix is the
* warning, and the single importer is what keeps it honest.
*/
// @provenance openRepoUnguarded kind=aligned level=2 ref=sdk/js/lib-wasm/src/lib.rs:doc_subscribe — the same open without the reach guard; internal
export async function openRepoUnguarded(nuri: Nuri): Promise<void> {
// Drop the registry if the session changed (in-page re-login → fresh verifier).
await syncSession();
@@ -274,6 +280,7 @@ export async function openRepoUnguarded(nuri: Nuri): Promise<void> {
* Open a SET of repos before an anchored batch read, in parallel, each tolerant
* ({@link ensureRepoOpen} never throws). Empty / falsy entries are ignored.
*/
// @provenance ensureReposOpen kind=aligned level=2 ref=sdk/js/lib-wasm/src/lib.rs:doc_subscribe — the batch form, with per-doc isolation
export async function ensureReposOpen(nuris: Nuri[]): Promise<void> {
const unique = [...new Set(nuris.filter(Boolean))];
if (unique.length === 0) return;
@@ -110,6 +110,7 @@ import type { Nuri, ReadCap } from "../model/types";
const attempted = new Map<Nuri, Promise<ReadCap | null>>();
/** Forget every outer-overlay fetch (tests / a switched session or wallet). */
// @provenance resetPublicStoreFetches kind=invention level=none ref=none — forgets the memoised fetches; upstream there is nothing to memoise, the broker answers
export function resetPublicStoreFetches(): void {
attempted.clear();
}
@@ -130,6 +131,7 @@ export function resetPublicStoreFetches(): void {
* caller `createEntityDoc` already refuses to hand back a reference whose bookkeeping did
* not land, for the same reason and in the same words.
*/
// @provenance exposeReadCap kind=divergent level=1 ref=engine/net/src/types.rs:PublicRepoLinkV0 — upstream NOTHING is written to make a repo public: the store is public and the broker exposes its outer overlay. Here the cap is written on the document's Header branch
export async function exposeReadCap(doc: Nuri, cap: ReadCap): Promise<void> {
const s = await session();
try {
@@ -164,6 +166,7 @@ export async function exposeReadCap(doc: Nuri, cap: ReadCap): Promise<void> {
* Never throws — a document that is not in a public store simply answers nothing, which
* is not an error but the normal case.
*/
// @provenance fetchReadCap kind=declared-not-wired level=1 ref=engine/net/src/types.rs:PublicRepoLinkV0 — the type DECLARES the cap is downloaded from the outer overlay if the brokers allow; it is constructed nowhere, both `PinRepo` constructors hard-code `expose_outer: false`, and `ExtTopicSyncReq` is `unimplemented!()`
export async function fetchReadCap(docLike: Nuri): Promise<boolean> {
const doc = targetOf(docLike);
const caps = getCaps();
@@ -221,6 +224,7 @@ async function downloadReadCap(doc: Nuri): Promise<ReadCap | null> {
* Ask for a SET of documents' caps, in parallel — what a batch read does before it
* decides which documents it may touch. Each fetch is independent and tolerant.
*/
// @provenance fetchReadCaps kind=declared-not-wired level=1 ref=engine/net/src/types.rs:PublicRepoLinkV0 — the batch form of the same unwired mechanism
export async function fetchReadCaps(docs: Nuri[]): Promise<void> {
const unique = [...new Set(docs.filter(Boolean))];
if (unique.length === 0) return;
@@ -71,6 +71,7 @@ import type { Nuri } from "../model/types";
* fixes is which ring the question is about, so that work decided for one identity is not
* judged against another's possession.
*/
// @provenance mayReach kind=aligned level=1 ref=engine/verifier/src/verifier.rs:load_repo_from_read_cap — upstream possession decides by whether the key opens the repo at all; here it is a lookup, because nothing is encrypted yet
export function mayReach(nuri: Nuri, holderKey?: string): boolean {
const caps = getCaps();
if (!caps.isEnforcing()) return true;
@@ -94,6 +95,7 @@ export function mayReach(nuri: Nuri, holderKey?: string): boolean {
* {@link mayReach}. The refusal names it too, or a processor's refusal would read as the
* connected identity's, which is the one thing nobody would then go and check.
*/
// @provenance assertMayReach kind=aligned level=1 ref=engine/verifier/src/verifier.rs:load_repo_from_read_cap — the throwing form, at the passage points; upstream the equivalent failure is a repo that simply never decrypts
export function assertMayReach(nuri: Nuri, op: string, holderKey?: string): void {
if (mayReach(nuri, holderKey)) return;
const who = holderKey === undefined ? "the connected user" : `holder ${JSON.stringify(holderKey)}`;
@@ -144,6 +146,7 @@ export function assertMayReach(nuri: Nuri, op: string, holderKey?: string): void
* `docs.registerUpdate`, because a store document is not OWNED in this sense — it IS a
* store, and the verifier commits to it on its own behalf.
*/
// @provenance assertMayWrite kind=aligned level=1 ref=engine/repo/src/commit.rs:verify_perm — upstream the right to write is membership of the repo, checked on commits only; ownership stands in for it here
export async function assertMayWrite(nuri: Nuri, op: string): Promise<void> {
const caps = getCaps();
if (!caps.isEnforcing()) return;
@@ -175,6 +178,7 @@ export async function assertMayWrite(nuri: Nuri, op: string): Promise<void> {
*
* `holderKey` names the ring the question is about — see {@link mayReach}.
*/
// @provenance mustNotAttempt kind=aligned level=1 ref=engine/verifier/src/request_processor.rs:resolve_target — upstream a repo you cannot open answers `RepoNotFound`; this is the do-not-even-attempt form of the same absence
export function mustNotAttempt(nuri: Nuri, holderKey?: string): boolean {
return !mayReach(nuri, holderKey);
}
@@ -54,6 +54,7 @@ function readable(item: unknown, caps: CapRegistry): boolean {
}
/** Pure: keep only the items whose document the current holder holds. */
// @provenance filterReadable kind=aligned level=1 ref=engine/verifier/src/verifier.rs:load_repo_from_read_cap — upstream the broker only delivers what the wallet's keys decrypt; the access unit is the DOCUMENT, which is why this filters per `@graph`
export function filterReadable<T>(items: Iterable<T>, caps: CapRegistry): T[] {
const out: T[] = [];
for (const item of items) if (readable(item, caps)) out.push(item);
@@ -85,6 +86,7 @@ export function filterReadable<T>(items: Iterable<T>, caps: CapRegistry): T[] {
* Everything that is not a function passes through untouched (`size` is handled above):
* a plain property carries no items.
*/
// @provenance makeReadFilteredView kind=aligned level=1 ref=engine/verifier/src/verifier.rs:load_repo_from_read_cap — the same filter as a live view over a reactive set; removed at migration
export function makeReadFilteredView<S extends object>(set: S, caps: CapRegistry): S {
const keep = (item: unknown): boolean => readable(item, caps);
/** The readable items, as a plain array — what every handled member works from. */
@@ -41,6 +41,7 @@ import type { Nuri } from "../model/types";
* during someone else's session. The guard still fires, against the named ring; see
* {@link assertMayReach}.
*/
// @provenance registerUpdate kind=aligned level=1 ref=engine/repo/src/types.rs:BranchCrdt — upstream these are service commits on branches whose CRDT is `None`, made by the verifier on its own behalf; here they are SPARQL writes that skip the ownership guard
export async function registerUpdate(
sessionId: string | number,
query: string,
@@ -79,6 +80,7 @@ function forHolderSuffix(holderKey: string | undefined): string {
*
* Never exported from the package — it reads a document the connected identity may not.
*/
// @provenance readForHolder kind=invention level=none ref=none — reading on behalf of an identity other than the session's exists only because one wallet hosts every identity
export async function readForHolder(
sessionId: string | number,
query: string,
@@ -115,6 +117,7 @@ export async function readForHolder(
* The recipient's ownership of the inbox is what bounds this: `inbox.post` is the
* only caller, and reading is guarded separately (`inbox.read`).
*/
// @provenance depositInto kind=aligned level=1 ref=engine/verifier/src/inbox_processor.rs:post_to_inbox — the one write that legitimately crosses: upstream a deposit is an anonymous sealed box, so it holds no cap and gets nothing back
export async function depositInto(
sessionId: string | number,
query: string,