@real-life/trust-protocol 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/README.md +187 -78
- package/dist/ack.d.ts +84 -0
- package/dist/ack.d.ts.map +1 -0
- package/dist/ack.js +114 -0
- package/dist/ack.js.map +1 -0
- package/dist/adapters/vti-mediator.d.ts +154 -0
- package/dist/adapters/vti-mediator.d.ts.map +1 -0
- package/dist/adapters/vti-mediator.js +621 -0
- package/dist/adapters/vti-mediator.js.map +1 -0
- package/dist/anchor.d.ts +226 -0
- package/dist/anchor.d.ts.map +1 -0
- package/dist/anchor.js +347 -0
- package/dist/anchor.js.map +1 -0
- package/dist/{holder.d.ts → carrier-holder.d.ts} +1 -1
- package/dist/carrier-holder.d.ts.map +1 -0
- package/dist/{holder.js → carrier-holder.js} +5 -4
- package/dist/carrier-holder.js.map +1 -0
- package/dist/carrier-identity.js +4 -4
- package/dist/carrier-identity.js.map +1 -1
- package/dist/carrier.d.ts.map +1 -1
- package/dist/carrier.js +4 -3
- package/dist/carrier.js.map +1 -1
- package/dist/ceremony.d.ts +3 -2
- package/dist/ceremony.d.ts.map +1 -1
- package/dist/ceremony.js +16 -26
- package/dist/ceremony.js.map +1 -1
- package/dist/codec.d.ts +46 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +410 -0
- package/dist/codec.js.map +1 -0
- package/dist/continuity.d.ts +67 -0
- package/dist/continuity.d.ts.map +1 -0
- package/dist/continuity.js +110 -0
- package/dist/continuity.js.map +1 -0
- package/dist/core.d.ts +4 -0
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js.map +1 -1
- package/dist/crypto.d.ts +23 -7
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js +54 -20
- package/dist/crypto.js.map +1 -1
- package/dist/delivery.d.ts +31 -3
- package/dist/delivery.d.ts.map +1 -1
- package/dist/delivery.js +75 -28
- package/dist/delivery.js.map +1 -1
- package/dist/encounter/ceremony.d.ts +37 -0
- package/dist/encounter/ceremony.d.ts.map +1 -0
- package/dist/encounter/ceremony.js +662 -0
- package/dist/encounter/ceremony.js.map +1 -0
- package/dist/encounter.d.ts +91 -1
- package/dist/encounter.d.ts.map +1 -1
- package/dist/encounter.js +191 -12
- package/dist/encounter.js.map +1 -1
- package/dist/engine.d.ts +291 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +1395 -0
- package/dist/engine.js.map +1 -0
- package/dist/entropy.d.ts +28 -0
- package/dist/entropy.d.ts.map +1 -0
- package/dist/entropy.js +96 -0
- package/dist/entropy.js.map +1 -0
- package/dist/events.d.ts +177 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +2 -0
- package/dist/events.js.map +1 -0
- package/dist/fixtures.d.ts +30 -0
- package/dist/fixtures.d.ts.map +1 -0
- package/dist/fixtures.js +155 -0
- package/dist/fixtures.js.map +1 -0
- package/dist/forge.d.ts +47 -0
- package/dist/forge.d.ts.map +1 -0
- package/dist/forge.js +20 -0
- package/dist/forge.js.map +1 -0
- package/dist/group-star.d.ts +251 -0
- package/dist/group-star.d.ts.map +1 -0
- package/dist/group-star.js +348 -0
- package/dist/group-star.js.map +1 -0
- package/dist/holder-api.d.ts +137 -0
- package/dist/holder-api.d.ts.map +1 -0
- package/dist/holder-api.js +132 -0
- package/dist/holder-api.js.map +1 -0
- package/dist/holder-state-v1.d.ts +801 -0
- package/dist/holder-state-v1.d.ts.map +1 -0
- package/dist/holder-state-v1.js +2 -0
- package/dist/holder-state-v1.js.map +1 -0
- package/dist/identity-state.d.ts +43 -0
- package/dist/identity-state.d.ts.map +1 -0
- package/dist/identity-state.js +345 -0
- package/dist/identity-state.js.map +1 -0
- package/dist/identity.d.ts +24 -2
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +70 -11
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +77 -29
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +36 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +22 -0
- package/dist/internal.js.map +1 -0
- package/dist/introduction/holder.d.ts +18 -0
- package/dist/introduction/holder.d.ts.map +1 -0
- package/dist/introduction/holder.js +757 -0
- package/dist/introduction/holder.js.map +1 -0
- package/dist/introduction.d.ts +101 -0
- package/dist/introduction.d.ts.map +1 -0
- package/dist/introduction.js +132 -0
- package/dist/introduction.js.map +1 -0
- package/dist/invariants.d.ts +43 -0
- package/dist/invariants.d.ts.map +1 -0
- package/dist/invariants.js +883 -0
- package/dist/invariants.js.map +1 -0
- package/dist/keys-seed.d.ts +7 -0
- package/dist/keys-seed.d.ts.map +1 -0
- package/dist/keys-seed.js +133 -0
- package/dist/keys-seed.js.map +1 -0
- package/dist/log-memory.d.ts +12 -0
- package/dist/log-memory.d.ts.map +1 -0
- package/dist/log-memory.js +101 -0
- package/dist/log-memory.js.map +1 -0
- package/dist/membership/holder.d.ts +35 -0
- package/dist/membership/holder.d.ts.map +1 -0
- package/dist/membership/holder.js +852 -0
- package/dist/membership/holder.js.map +1 -0
- package/dist/membership.d.ts +92 -0
- package/dist/membership.d.ts.map +1 -0
- package/dist/membership.js +157 -0
- package/dist/membership.js.map +1 -0
- package/dist/ports.d.ts +237 -0
- package/dist/ports.d.ts.map +1 -0
- package/dist/ports.js +2 -0
- package/dist/ports.js.map +1 -0
- package/dist/profile.d.ts +56 -0
- package/dist/profile.d.ts.map +1 -0
- package/dist/profile.js +193 -0
- package/dist/profile.js.map +1 -0
- package/dist/prompts.d.ts +14 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +69 -0
- package/dist/prompts.js.map +1 -0
- package/dist/receive.d.ts +133 -0
- package/dist/receive.d.ts.map +1 -0
- package/dist/receive.js +298 -0
- package/dist/receive.js.map +1 -0
- package/dist/results.d.ts +158 -0
- package/dist/results.d.ts.map +1 -0
- package/dist/results.js +21 -0
- package/dist/results.js.map +1 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +42 -38
- package/dist/schemas.js.map +1 -1
- package/dist/sha256.d.ts +3 -0
- package/dist/sha256.d.ts.map +1 -0
- package/dist/sha256.js +69 -0
- package/dist/sha256.js.map +1 -0
- package/dist/star.d.ts +31 -0
- package/dist/star.d.ts.map +1 -0
- package/dist/star.js +56 -0
- package/dist/star.js.map +1 -0
- package/dist/state-builder.d.ts +42 -0
- package/dist/state-builder.d.ts.map +1 -0
- package/dist/state-builder.js +100 -0
- package/dist/state-builder.js.map +1 -0
- package/dist/state.d.ts +853 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +36 -0
- package/dist/state.js.map +1 -0
- package/dist/store-contract.d.ts +11 -0
- package/dist/store-contract.d.ts.map +1 -0
- package/dist/store-contract.js +189 -0
- package/dist/store-contract.js.map +1 -0
- package/dist/store-memory.d.ts +8 -0
- package/dist/store-memory.d.ts.map +1 -0
- package/dist/store-memory.js +17 -0
- package/dist/store-memory.js.map +1 -0
- package/dist/testing.d.ts +22 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +21 -0
- package/dist/testing.js.map +1 -0
- package/dist/trust/continuity.d.ts +71 -0
- package/dist/trust/continuity.d.ts.map +1 -0
- package/dist/trust/continuity.js +1216 -0
- package/dist/trust/continuity.js.map +1 -0
- package/dist/trust/duties.d.ts +67 -0
- package/dist/trust/duties.d.ts.map +1 -0
- package/dist/trust/duties.js +179 -0
- package/dist/trust/duties.js.map +1 -0
- package/dist/trust/entries.d.ts +139 -0
- package/dist/trust/entries.d.ts.map +1 -0
- package/dist/trust/entries.js +694 -0
- package/dist/trust/entries.js.map +1 -0
- package/dist/trust/group-star.d.ts +43 -0
- package/dist/trust/group-star.d.ts.map +1 -0
- package/dist/trust/group-star.js +188 -0
- package/dist/trust/group-star.js.map +1 -0
- package/dist/trust/mapping.d.ts +56 -0
- package/dist/trust/mapping.d.ts.map +1 -0
- package/dist/trust/mapping.js +584 -0
- package/dist/trust/mapping.js.map +1 -0
- package/dist/trust/profile.d.ts +25 -0
- package/dist/trust/profile.d.ts.map +1 -0
- package/dist/trust/profile.js +249 -0
- package/dist/trust/profile.js.map +1 -0
- package/dist/trust/star.d.ts +208 -0
- package/dist/trust/star.d.ts.map +1 -0
- package/dist/trust/star.js +588 -0
- package/dist/trust/star.js.map +1 -0
- package/dist/trust/state.d.ts +83 -0
- package/dist/trust/state.d.ts.map +1 -0
- package/dist/trust/state.js +154 -0
- package/dist/trust/state.js.map +1 -0
- package/dist/util-freeze.d.ts +3 -0
- package/dist/util-freeze.d.ts.map +1 -0
- package/dist/util-freeze.js +11 -0
- package/dist/util-freeze.js.map +1 -0
- package/dist/views.d.ts +147 -0
- package/dist/views.d.ts.map +1 -0
- package/dist/views.js +268 -0
- package/dist/views.js.map +1 -0
- package/dist/visibility.d.ts +5 -5
- package/dist/visibility.d.ts.map +1 -1
- package/dist/visibility.js +22 -28
- package/dist/visibility.js.map +1 -1
- package/dist/wire.d.ts +178 -84
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js.map +1 -1
- package/package.json +58 -11
- package/schemas/holder-state-v1.schema.json +3880 -0
- package/dist/holder.d.ts.map +0 -1
- package/dist/holder.js.map +0 -1
- package/dist/probe/acks.d.ts +0 -27
- package/dist/probe/acks.d.ts.map +0 -1
- package/dist/probe/acks.js +0 -152
- package/dist/probe/acks.js.map +0 -1
- package/dist/probe/continuity.d.ts +0 -20
- package/dist/probe/continuity.d.ts.map +0 -1
- package/dist/probe/continuity.js +0 -805
- package/dist/probe/continuity.js.map +0 -1
- package/dist/probe/deps.d.ts +0 -61
- package/dist/probe/deps.d.ts.map +0 -1
- package/dist/probe/deps.js +0 -54
- package/dist/probe/deps.js.map +0 -1
- package/dist/probe/encounter.d.ts +0 -26
- package/dist/probe/encounter.d.ts.map +0 -1
- package/dist/probe/encounter.js +0 -938
- package/dist/probe/encounter.js.map +0 -1
- package/dist/probe/introduce.d.ts +0 -70
- package/dist/probe/introduce.d.ts.map +0 -1
- package/dist/probe/introduce.js +0 -295
- package/dist/probe/introduce.js.map +0 -1
- package/dist/probe/membership.d.ts +0 -90
- package/dist/probe/membership.d.ts.map +0 -1
- package/dist/probe/membership.js +0 -450
- package/dist/probe/membership.js.map +0 -1
- package/dist/probe/trust.d.ts +0 -156
- package/dist/probe/trust.d.ts.map +0 -1
- package/dist/probe/trust.js +0 -1233
- package/dist/probe/trust.js.map +0 -1
- package/dist/probe.d.ts +0 -7
- package/dist/probe.d.ts.map +0 -1
- package/dist/probe.js +0 -42
- package/dist/probe.js.map +0 -1
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { handlerPrepared } from './receive.js';
|
|
2
|
+
/** The command name of the decision. */
|
|
3
|
+
export const DECIDE = 'prompt.decide';
|
|
4
|
+
const KINDS = ['encounter-confirm', 'group-invite', 'introduction'];
|
|
5
|
+
/** The decision handlers of the modules, one per kind at most. */
|
|
6
|
+
export function collectDecisions(modules) {
|
|
7
|
+
const out = new Map();
|
|
8
|
+
for (const m of modules) {
|
|
9
|
+
for (const [kind, h] of Object.entries(m?.decisions ?? {})) {
|
|
10
|
+
if (!KINDS.includes(kind))
|
|
11
|
+
throw new Error(`unknown prompt kind ${kind} (module ${m.name})`);
|
|
12
|
+
if (out.has(kind))
|
|
13
|
+
throw new Error(`duplicate decision handler ${kind} (module ${m.name})`);
|
|
14
|
+
if (typeof h !== 'function' && (h === null || typeof h !== 'object' || typeof h.apply !== 'function' || (h.prepare !== undefined && typeof h.prepare !== 'function'))) {
|
|
15
|
+
throw new TypeError(`decision handler ${kind} (module ${m.name}) must be a function or {prepare?, apply}`);
|
|
16
|
+
}
|
|
17
|
+
out.set(kind, h);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
const validInput = (input) => input !== null && typeof input === 'object' && typeof input.promptId === 'string' && (input.choice === 'accept' || input.choice === 'decline');
|
|
23
|
+
const decideDef = (decisions) => ({
|
|
24
|
+
human: true,
|
|
25
|
+
// a prepared handler's preparation, against the snapshot apply sees;
|
|
26
|
+
// nothing for an unknown, expired or malformed decision (apply answers it)
|
|
27
|
+
async prepare(ctx, input) {
|
|
28
|
+
if (!validInput(input) || !Object.hasOwn(ctx.snapshot.prompts, input.promptId))
|
|
29
|
+
return undefined;
|
|
30
|
+
const p = ctx.snapshot.prompts[input.promptId];
|
|
31
|
+
if (p.expiresAt !== undefined && p.expiresAt <= ctx.when)
|
|
32
|
+
return undefined;
|
|
33
|
+
const h = decisions.get(p.kind);
|
|
34
|
+
return h && typeof h !== 'function' && h.prepare ? h.prepare(ctx, p, input.choice) : undefined;
|
|
35
|
+
},
|
|
36
|
+
apply(state, prepared, input, when) {
|
|
37
|
+
if (input === null || typeof input !== 'object' || typeof input.promptId !== 'string')
|
|
38
|
+
throw new TypeError('prompt.decide needs {promptId: string, choice}');
|
|
39
|
+
if (input.choice !== 'accept' && input.choice !== 'decline')
|
|
40
|
+
throw new TypeError(`prompt.decide: choice must be accept or decline, got ${String(input.choice)}`);
|
|
41
|
+
const { promptId, choice } = input;
|
|
42
|
+
if (!Object.hasOwn(state.prompts, promptId))
|
|
43
|
+
return { ok: false, code: 'unknown-prompt' };
|
|
44
|
+
const p = state.prompts[promptId];
|
|
45
|
+
if (p.expiresAt !== undefined && p.expiresAt <= when)
|
|
46
|
+
return { ok: false, code: 'prompt-expired' };
|
|
47
|
+
const handler = decisions.get(p.kind);
|
|
48
|
+
const r = !handler ? { state: state }
|
|
49
|
+
: typeof handler === 'function' ? handler(state, p, choice, when)
|
|
50
|
+
: handler.apply(state, p, choice, when, handlerPrepared(prepared, prepared.value));
|
|
51
|
+
if (r.ok === false)
|
|
52
|
+
return r;
|
|
53
|
+
const done = r;
|
|
54
|
+
const prompts = { ...done.state.prompts };
|
|
55
|
+
delete prompts[promptId];
|
|
56
|
+
const decided = { type: 'prompt.decided', promptId, kind: p.kind, choice };
|
|
57
|
+
return {
|
|
58
|
+
state: { ...done.state, prompts },
|
|
59
|
+
...(done.outbound ? { outbound: done.outbound } : {}),
|
|
60
|
+
...(done.duties ? { duties: done.duties } : {}),
|
|
61
|
+
events: [...(done.events ?? []), decided],
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
/** The prompts module createHolder registers, over the modules' decision handlers. */
|
|
66
|
+
export function promptsModule(decisions = new Map()) {
|
|
67
|
+
return Object.freeze({ name: 'prompts', commands: Object.freeze({ [DECIDE]: decideDef(decisions) }) });
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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","sourcesContent":["// prompts — the human's open decisions and the act that closes them\n// (lib Stage 2, note §2.1 prompts, §4.4, §4.5).\n//\n// Domain modules open prompts (encounter-confirm, group-invite,\n// introduction) inside their own transitions and announce prompt.opened;\n// this module closes them. `prompt.decide` is one human act (journaled\n// under the app's actId). createHolder registers this module beside the\n// domain modules, so its command name is taken.\n//\n// What a choice does in its domain (joining the group, confirming the\n// encounter, accepting the introduction) belongs to the module that opens\n// that kind of prompt: it registers a DecisionHandler for the kind\n// (HolderModule.decisions). The decision runs that handler in its own\n// transition, so the domain effect, its outbound and duties, and the\n// closing of the prompt commit together or not at all; a handler's\n// refusal refuses the decision. A kind without a handler is only closed.\n// The events are the handler's, then prompt.decided. At most one handler\n// per kind across all modules; a second, an unknown kind or a handler\n// that is no function throws when the holder is built.\n//\n// Expiry: a prompt with expiresAt <= when is refused as prompt-expired;\n// the refusal commits nothing, so the prompt stays until tick removes it\n// (engine.ts, built-in tick). An id without an open prompt is\n// unknown-prompt. A malformed input (a promptId that is no string, a\n// choice other than accept or decline) is a programming error and throws.\n//\n// A handler that signs or seals (PR 7: the counter-step, the membership\n// accept, the introduction's consent) is the prepared form {prepare?,\n// apply}: its preparation runs in the decision's own preparation, against\n// the snapshot its apply then sees (engine.ts, step 2).\nimport type { Applied, CommandDef, DecisionDef, DecisionHandler, EventDraft, HolderModule, Refusal } from './engine.js'\nimport { handlerPrepared } from './receive.js'\nimport type { HolderState, PromptChoice, PromptKind } from './state.js'\n\n/** The command name of the decision. */\nexport const DECIDE = 'prompt.decide'\n\nexport interface DecideInput { promptId: string, choice: PromptChoice }\n\nconst KINDS: readonly PromptKind[] = ['encounter-confirm', 'group-invite', 'introduction']\n\nexport type Decisions = ReadonlyMap<PromptKind, DecisionHandler>\n\n/** The decision handlers of the modules, one per kind at most. */\nexport function collectDecisions (modules: readonly HolderModule[]): Decisions {\n const out = new Map<PromptKind, DecisionHandler>()\n for (const m of modules) {\n for (const [kind, h] of Object.entries(m?.decisions ?? {})) {\n if (!(KINDS as readonly string[]).includes(kind)) throw new Error(`unknown prompt kind ${kind} (module ${m.name})`)\n if (out.has(kind as PromptKind)) throw new Error(`duplicate decision handler ${kind} (module ${m.name})`)\n if (typeof h !== 'function' && (h === null || typeof h !== 'object' || typeof (h as DecisionDef).apply !== 'function' || ((h as DecisionDef).prepare !== undefined && typeof (h as DecisionDef).prepare !== 'function'))) {\n throw new TypeError(`decision handler ${kind} (module ${m.name}) must be a function or {prepare?, apply}`)\n }\n out.set(kind as PromptKind, h)\n }\n }\n return out\n}\n\nconst validInput = (input: DecideInput): boolean =>\n input !== null && typeof input === 'object' && typeof input.promptId === 'string' && (input.choice === 'accept' || input.choice === 'decline')\n\nconst decideDef = (decisions: Decisions): CommandDef<DecideInput, unknown> => ({\n human: true,\n // a prepared handler's preparation, against the snapshot apply sees;\n // nothing for an unknown, expired or malformed decision (apply answers it)\n async prepare (ctx, input) {\n if (!validInput(input) || !Object.hasOwn(ctx.snapshot.prompts, input.promptId)) return undefined\n const p = ctx.snapshot.prompts[input.promptId]\n if (p.expiresAt !== undefined && p.expiresAt <= ctx.when) return undefined\n const h = decisions.get(p.kind)\n return h && typeof h !== 'function' && h.prepare ? h.prepare(ctx, p, input.choice) : undefined\n },\n apply (state, prepared, input, when) {\n if (input === null || typeof input !== 'object' || typeof input.promptId !== 'string') throw new TypeError('prompt.decide needs {promptId: string, choice}')\n if (input.choice !== 'accept' && input.choice !== 'decline') throw new TypeError(`prompt.decide: choice must be accept or decline, got ${String(input.choice)}`)\n const { promptId, choice } = input\n if (!Object.hasOwn(state.prompts, promptId)) return { ok: false, code: 'unknown-prompt' }\n const p = state.prompts[promptId]\n if (p.expiresAt !== undefined && p.expiresAt <= when) return { ok: false, code: 'prompt-expired' }\n const handler = decisions.get(p.kind)\n const r: Applied | Refusal = !handler ? { state: state as HolderState }\n : typeof handler === 'function' ? handler(state, p, choice, when)\n : handler.apply(state, p, choice, when, handlerPrepared(prepared, prepared.value))\n if ((r as Refusal).ok === false) return r as Refusal\n const done = r as Applied\n const prompts = { ...done.state.prompts }\n delete prompts[promptId]\n const decided: EventDraft = { type: 'prompt.decided', promptId, kind: p.kind, choice }\n return {\n state: { ...done.state, prompts },\n ...(done.outbound ? { outbound: done.outbound } : {}),\n ...(done.duties ? { duties: done.duties } : {}),\n events: [...(done.events ?? []), decided],\n }\n },\n})\n\n/** The prompts module createHolder registers, over the modules' decision handlers. */\nexport function promptsModule (decisions: Decisions = new Map()): HolderModule {\n return Object.freeze({ name: 'prompts', commands: Object.freeze({ [DECIDE]: decideDef(decisions) }) })\n}\n"]}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { Json } from './core.js';
|
|
2
|
+
import type { HolderState, Millis, Relationship, StoredAck, Tuple } from './state.js';
|
|
3
|
+
/** An ack as sealed in the preparation; the engine adds its schedule. */
|
|
4
|
+
export type SealedAck = Pick<StoredAck, 'digest' | 'envelope' | 'threadId' | 'recipient'>;
|
|
5
|
+
import type { Outbound } from './ports.js';
|
|
6
|
+
import type { ReceiveResult } from './results.js';
|
|
7
|
+
import type { EventDraft, PrepareCtx, Prepared } from './engine.js';
|
|
8
|
+
/** Where and when a document arrived: the own rkid it was sealed to, its
|
|
9
|
+
* thread, its digest and the receive's `when`. */
|
|
10
|
+
export interface Arrival {
|
|
11
|
+
rkid: string;
|
|
12
|
+
threadId: string;
|
|
13
|
+
digest: string;
|
|
14
|
+
when: Millis;
|
|
15
|
+
}
|
|
16
|
+
/** Why a task handler refuses a document; the stage follows from where:
|
|
17
|
+
* decode 'malformed' → 7, decode or prepare otherwise → 8, apply → 9. */
|
|
18
|
+
export type TaskFailure = 'malformed' | 'validation-failed' | 'stale-issuance' | 'gate-future' | 'consumed-challenge';
|
|
19
|
+
/** A handler's refusal: nothing commits, the digest stays uncached and
|
|
20
|
+
* a redelivery is evaluated afresh (Delivery 6.2 stage 4) — with one
|
|
21
|
+
* narrow, enumerated exception, the Encounter aging latch: an apply that
|
|
22
|
+
* refuses because its authoritative resolution found an own challenge past
|
|
23
|
+
* its age bound (Encounter 5260, 5270, 5290; Delivery 4.1 check 5) returns
|
|
24
|
+
* `latch`, the state with that challenge removed, and the engine commits
|
|
25
|
+
* exactly it (and the raised lastWhen): no cache entry, no ack, no event;
|
|
26
|
+
* the disposition stays failed. A latch that touches anything beyond
|
|
27
|
+
* encounter.challenges is a programming error and throws (engine.ts). */
|
|
28
|
+
export interface TaskRefusal {
|
|
29
|
+
ok: false;
|
|
30
|
+
reason: TaskFailure;
|
|
31
|
+
ref?: string;
|
|
32
|
+
latch?: HolderState;
|
|
33
|
+
}
|
|
34
|
+
/** A discard at a resource limit (Trust 5365/5366), answered by apply:
|
|
35
|
+
* `state` commits (assembly dropped, lower bound held), the disposition
|
|
36
|
+
* is `discarded`, with no cache entry, no ack and no event. */
|
|
37
|
+
export interface TaskDiscarded {
|
|
38
|
+
discarded: true;
|
|
39
|
+
reason: DiscardReason;
|
|
40
|
+
state: HolderState;
|
|
41
|
+
ref?: string;
|
|
42
|
+
}
|
|
43
|
+
/** Why an assembly was discarded: a local resource limit (5365), or an
|
|
44
|
+
* authenticated violation of the assembly rules that rejects the delivery. */
|
|
45
|
+
export type DiscardReason = 'resource-limit' | 'rejected';
|
|
46
|
+
export declare const isTaskDiscarded: (x: unknown) => x is TaskDiscarded;
|
|
47
|
+
/** A received document after stage 7: the profile fields, its payload
|
|
48
|
+
* as the handler's decode returned it. Read-only. */
|
|
49
|
+
export interface ReceivedDocument<T = unknown> {
|
|
50
|
+
readonly id: string;
|
|
51
|
+
readonly type: string;
|
|
52
|
+
readonly issuer: string;
|
|
53
|
+
readonly recipient: string;
|
|
54
|
+
readonly threadId: string;
|
|
55
|
+
readonly issuedAt: string;
|
|
56
|
+
readonly payload: T;
|
|
57
|
+
readonly ceremony?: Json;
|
|
58
|
+
readonly proof?: Json;
|
|
59
|
+
}
|
|
60
|
+
/** A sealed ack as the outbound the app sends, at the given attempt. */
|
|
61
|
+
export declare const ackOutbound: (a: Readonly<SealedAck>, attempt: number) => Outbound;
|
|
62
|
+
/** Signature-class types (Delivery 4.2/4.4): payloads whose authenticity
|
|
63
|
+
* is a transferable signature; their acks are signed, not MACed. The
|
|
64
|
+
* `x-` slugs are this library's own experimental, unregistered forms
|
|
65
|
+
* for what the specifications leave to the application (the membership
|
|
66
|
+
* prelude, Membership 1.2; the welcome until the Access envelope is
|
|
67
|
+
* built; the introduction offer that conveys the target designator,
|
|
68
|
+
* Trust 8.3): signed documents as well. A receiver that does not know
|
|
69
|
+
* them answers unknown-type (Delivery §6.2). */
|
|
70
|
+
export declare const SIGNATURE_CLASS: ReadonlySet<string>;
|
|
71
|
+
/** The counterpart a `channel` binding names: the key agreement the ack
|
|
72
|
+
* is sealed to and the contact it is filed under. */
|
|
73
|
+
/** The binding a document arrives under: the counterpart's key and the
|
|
74
|
+
* contact; `via`, where the arrival key is no tuple's (a member key), the
|
|
75
|
+
* own rkid of the tuple the contact was named through (Recipient.via). */
|
|
76
|
+
export interface Channel {
|
|
77
|
+
keyAgreement: string;
|
|
78
|
+
contactId: string;
|
|
79
|
+
via?: string;
|
|
80
|
+
}
|
|
81
|
+
export declare const isTaskRefusal: (x: unknown) => x is TaskRefusal;
|
|
82
|
+
type Failed = Extract<ReceiveResult, {
|
|
83
|
+
disposition: 'failed';
|
|
84
|
+
}>;
|
|
85
|
+
/** What stages 1–8 decided, bound to the snapshot they ran against. */
|
|
86
|
+
export type ReceivePlan = {
|
|
87
|
+
kind: 'failed';
|
|
88
|
+
result: Failed;
|
|
89
|
+
} | {
|
|
90
|
+
kind: 'duplicate';
|
|
91
|
+
digest: string;
|
|
92
|
+
} | {
|
|
93
|
+
kind: 'ack';
|
|
94
|
+
digest: string;
|
|
95
|
+
ref: string;
|
|
96
|
+
} | {
|
|
97
|
+
kind: 'task';
|
|
98
|
+
digest: string;
|
|
99
|
+
type: string;
|
|
100
|
+
doc: ReceivedDocument;
|
|
101
|
+
arrival: Arrival;
|
|
102
|
+
value: unknown;
|
|
103
|
+
ack: SealedAck;
|
|
104
|
+
};
|
|
105
|
+
/** The handler surface the core needs (engine.ts TaskHandler). */
|
|
106
|
+
export interface TaskEntry {
|
|
107
|
+
proof: 'absent' | 'required';
|
|
108
|
+
decode(payload: unknown): unknown;
|
|
109
|
+
channel?(state: Readonly<HolderState>, doc: ReceivedDocument, rkid: string): Channel | TaskRefusal;
|
|
110
|
+
/** may arrive on a deactivated tuple an act pinned (engine TaskHandler) */
|
|
111
|
+
pinned?: true;
|
|
112
|
+
prepare?(ctx: PrepareCtx, doc: ReceivedDocument, arrival: Arrival): Promise<unknown>;
|
|
113
|
+
}
|
|
114
|
+
/** The tuple whose own rkid is `rkid`, with its relationship. */
|
|
115
|
+
export declare function tupleByRkid(state: Readonly<HolderState>, rkid: string): {
|
|
116
|
+
rel: Relationship;
|
|
117
|
+
tuple: Tuple;
|
|
118
|
+
} | null;
|
|
119
|
+
/**
|
|
120
|
+
* Stages 1–8 against the preparation's snapshot. Never throws for
|
|
121
|
+
* anything the envelope carries; port failures surface as InfraError.
|
|
122
|
+
*/
|
|
123
|
+
export declare function prepareReceive(ctx: PrepareCtx, env: unknown, tasks: ReadonlyMap<string, TaskEntry>): Promise<ReceivePlan>;
|
|
124
|
+
/** The outbox after a valid ack of `ref` (4.2, 6.1): delivered, late after
|
|
125
|
+
* failed; unchanged when already delivered. Shared with report(). */
|
|
126
|
+
export declare function markDelivered(state: Readonly<HolderState>, ref: string, when: Millis): {
|
|
127
|
+
outbox: HolderState['outbox'];
|
|
128
|
+
event: EventDraft | null;
|
|
129
|
+
};
|
|
130
|
+
/** Prepared for a handler: its own value under the receive's binding. */
|
|
131
|
+
export declare const handlerPrepared: <P>(p: Prepared<unknown>, value: P) => Prepared<P>;
|
|
132
|
+
export {};
|
|
133
|
+
//# sourceMappingURL=receive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receive.d.ts","sourceRoot":"","sources":["../src/receive.ts"],"names":[],"mappings":"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"}
|
package/dist/receive.js
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
// receive — the holder's receive core (lib Stage 2, note §4.3; Delivery
|
|
2
|
+
// §6.2, §4.2, §4.4). The engine runs it as its built-in `receive`: the
|
|
3
|
+
// preparation (async) walks stages 1–8, the transition (sync) is stage 9.
|
|
4
|
+
//
|
|
5
|
+
// 1–4 once, here, through delivery.receiveByAgreement: the key agreement
|
|
6
|
+
// is the KeyProvider's `agree` under the engine's release from
|
|
7
|
+
// `addresses` (a tombstone answers retired: stage 3; an rkid never
|
|
8
|
+
// issued answers unknown: stage 2); the completed-effect cache is
|
|
9
|
+
// `state.effects`
|
|
10
|
+
// 5 the document profile (schema, calendar-valid issuedAt) and
|
|
11
|
+
// recipient = the own anchor of the label the arrival rkid derives
|
|
12
|
+
// under (addresses)
|
|
13
|
+
// 6 dispatch by the full type URI with version: the built-in
|
|
14
|
+
// delivery-ack path, else the task register, else unknown-type;
|
|
15
|
+
// then the entry's proof declaration. Delivery §3 wants `proof`
|
|
16
|
+
// absent on every type but delivery-ack and registry-declaration,
|
|
17
|
+
// and §4.4 puts the declaration into the registry entry; the
|
|
18
|
+
// profile schema can name only the types it knows, so for
|
|
19
|
+
// companion types the rule is enforced here, the earliest stage at
|
|
20
|
+
// which the receiver holds the entry: a mismatch is
|
|
21
|
+
// failed(validation-failed)
|
|
22
|
+
// 7–8 the handler's decode (malformed at 7, any other refusal at 8),
|
|
23
|
+
// the core's closed acceptance binding (Delivery 4.4: the arrival
|
|
24
|
+
// tuple is selected by rkid, the document's issuer is its
|
|
25
|
+
// counterpart anchor), the handler's prepare, and the ack: sealed
|
|
26
|
+
// here, before the transaction, from fresh entropy
|
|
27
|
+
// 9 the handler's apply; the core files the effect-cache entry with
|
|
28
|
+
// the ack in the same commit (the handler never writes `effects`)
|
|
29
|
+
// and hands the ack out first among the outbound
|
|
30
|
+
//
|
|
31
|
+
// Acks (delivery-ack/0.1) are no registered task: one common path checks
|
|
32
|
+
// the form (ack.ts macAckForm), then the consistency of 4.2 against the
|
|
33
|
+
// outbox — `ref` is a document this holder sent on that thread, on the
|
|
34
|
+
// arrival tuple (outbox item rkid = arrival rkid), the issuer is that
|
|
35
|
+
// tuple's counterpart, the referenced document's type is of the
|
|
36
|
+
// designated-verifier class (a MAC ack of a signature-class document is
|
|
37
|
+
// the wrong class), and the MAC verifies under the arrival tuple's ack
|
|
38
|
+
// key. A valid ack marks the item delivered (late after failed) and
|
|
39
|
+
// earns a terminal cache entry, no ack of its own.
|
|
40
|
+
//
|
|
41
|
+
// The stage-9 lock set (Delivery 6.2): the engine serializes every
|
|
42
|
+
// operation of a holder in one queue and commits by CAS — a strictly
|
|
43
|
+
// stronger serialization than the lock set asks for (it holds every key
|
|
44
|
+
// of the holder, not only the overlapping ones), which is how this
|
|
45
|
+
// library implements it under Stage 2's one-writer contract. The lock set
|
|
46
|
+
// — the digest, and for star and group-star chunks additionally the
|
|
47
|
+
// assembly key (tuple, type, salt) of 4.4 — is held for the whole
|
|
48
|
+
// evaluation; a CAS conflict re-reads and re-enters at stage 1, which
|
|
49
|
+
// re-checks the cache at stage 4. The chunk types (trust/star.ts,
|
|
50
|
+
// trust/group-star.ts, PR 4b) need no key of their own here: every
|
|
51
|
+
// chunk of one tuple and type is evaluated against, and committed over,
|
|
52
|
+
// the one state version its preparation read, so the completing chunk's
|
|
53
|
+
// effect (validated assembly, accepted snapshot, completed-salt advance)
|
|
54
|
+
// commits with the cache entry and the ack in one transaction.
|
|
55
|
+
//
|
|
56
|
+
// A refusal (TaskRefusal) never commits anything, at any stage.
|
|
57
|
+
//
|
|
58
|
+
// A handler's apply may answer a TaskDiscarded: the receiver discarded an
|
|
59
|
+
// open assembly and holds its salt as the lower bound (5366), for one of
|
|
60
|
+
// two reasons: `resource-limit` (Trust 5365), or `rejected` — an
|
|
61
|
+
// authenticated chunk (its MAC verified) violates the assembly rules
|
|
62
|
+
// (5260–5310, 5500, 5510), and the spec rejects the whole delivery, so it
|
|
63
|
+
// must not complete from any later chunk. That is a spec-mandated state
|
|
64
|
+
// effect, not a failure of the document: its state commits and the result
|
|
65
|
+
// is the disposition `discarded` with the reason and the rule — no
|
|
66
|
+
// effect-cache entry (a redelivery is evaluated afresh and meets the lower
|
|
67
|
+
// bound), no ack (the delivery must not complete), no event; the completed
|
|
68
|
+
// high-water mark stays. A chunk that does not authenticate is a plain
|
|
69
|
+
// refusal and touches nothing. DELIVERY GAP: Delivery §6.2 names no
|
|
70
|
+
// disposition for a document whose processing ends in such a discard;
|
|
71
|
+
// `discarded` (both reasons) is this library's, to be registered in
|
|
72
|
+
// Delivery 0.82.
|
|
73
|
+
//
|
|
74
|
+
// A verified ack runs the ack handler a module registered for the
|
|
75
|
+
// acknowledged item's type, in the ack's transaction (engine.ts
|
|
76
|
+
// AckHandler): the sender side of 5660, completion by verified acks only.
|
|
77
|
+
//
|
|
78
|
+
// Ack class (4.4): the class follows the payload's audience class. The
|
|
79
|
+
// types of SIGNATURE_CLASS carry transferable signatures (the encounter
|
|
80
|
+
// carriers, the membership documents, the signed introduction artifacts,
|
|
81
|
+
// the registry declaration): their ack is SIGNED, an eddsa-jcs-2022 proof
|
|
82
|
+
// under the ack's issuer anchor through the KeyProvider (`sign` with the
|
|
83
|
+
// arrival key's label). Every other type is designated-verifier and earns
|
|
84
|
+
// the MAC form under the channel ack key of the arrival rkid and the
|
|
85
|
+
// counterpart key. A received ack is checked in the form its referenced
|
|
86
|
+
// outbox item's class selects; the other form is validation-failed.
|
|
87
|
+
//
|
|
88
|
+
// The acceptance binding before a tuple exists (PR 7): a handler with a
|
|
89
|
+
// `channel` binds its document itself, from the document, where it may
|
|
90
|
+
// arrive on an own key no tuple carries yet — the encounter bundle on the
|
|
91
|
+
// displayed card's key (Delivery 4.1: the bundle establishes the tuple,
|
|
92
|
+
// its issuer bound to card.anchor = credential.issuer), the membership
|
|
93
|
+
// documents on member keys (Membership 3.1, 3.2). `channel` names the
|
|
94
|
+
// counterpart's key agreement the ack is sealed to and the contact it is
|
|
95
|
+
// filed under, or refuses (stage 7 for malformed, else 8). Every other
|
|
96
|
+
// handler keeps the tuple binding of Delivery 4.4.
|
|
97
|
+
import { calOK, iso, makeValidator, toU } from './core.js';
|
|
98
|
+
import { diSignWith, diVerify, digestDoc, xRawOfMk } from './crypto.js';
|
|
99
|
+
import { receiveByAgreement, seal } from './delivery.js';
|
|
100
|
+
import { ACK_TYPE, ackDocument, ackKeyOf, ackProofForm, macAck, macAckForm, macAckValid, signedAckForm } from './ack.js';
|
|
101
|
+
import { SCHEMAS } from './schemas.js';
|
|
102
|
+
import { triasOf } from './state.js';
|
|
103
|
+
import { entryOf, liveRel } from './trust/state.js';
|
|
104
|
+
import { InfraError } from './results.js';
|
|
105
|
+
export const isTaskDiscarded = (x) => x !== null && typeof x === 'object' && x.discarded === true;
|
|
106
|
+
/** A sealed ack as the outbound the app sends, at the given attempt. */
|
|
107
|
+
export const ackOutbound = (a, attempt) => structuredClone({ digest: a.digest, envelope: a.envelope, type: ACK_TYPE, threadId: a.threadId, recipient: a.recipient, attempt });
|
|
108
|
+
const TT = 'https://real-life.org/trust-tasks/';
|
|
109
|
+
/** Signature-class types (Delivery 4.2/4.4): payloads whose authenticity
|
|
110
|
+
* is a transferable signature; their acks are signed, not MACed. The
|
|
111
|
+
* `x-` slugs are this library's own experimental, unregistered forms
|
|
112
|
+
* for what the specifications leave to the application (the membership
|
|
113
|
+
* prelude, Membership 1.2; the welcome until the Access envelope is
|
|
114
|
+
* built; the introduction offer that conveys the target designator,
|
|
115
|
+
* Trust 8.3): signed documents as well. A receiver that does not know
|
|
116
|
+
* them answers unknown-type (Delivery §6.2). */
|
|
117
|
+
export const SIGNATURE_CLASS = new Set([
|
|
118
|
+
TT + 'encounter-bundle/0.1',
|
|
119
|
+
TT + 'encounter-credential-delivery/0.1',
|
|
120
|
+
TT + 'membership-invite/0.2',
|
|
121
|
+
TT + 'membership-accept/0.2',
|
|
122
|
+
TT + 'membership-evidence/0.1',
|
|
123
|
+
TT + 'membership-evidence/0.2',
|
|
124
|
+
TT + 'registry-declaration/0.1',
|
|
125
|
+
TT + 'introduction-request/0.1',
|
|
126
|
+
TT + 'introduction-forward/0.1',
|
|
127
|
+
TT + 'introduction-reply/0.1',
|
|
128
|
+
TT + 'x-membership-prelude-request/0.1',
|
|
129
|
+
TT + 'x-membership-prelude-reply/0.1',
|
|
130
|
+
TT + 'x-membership-welcome/0.1',
|
|
131
|
+
TT + 'x-introduction-offer/0.1',
|
|
132
|
+
]);
|
|
133
|
+
export const isTaskRefusal = (x) => x !== null && typeof x === 'object' && x.ok === false && typeof x.reason === 'string';
|
|
134
|
+
const V = makeValidator(SCHEMAS);
|
|
135
|
+
const profileOk = (doc) => V.validate(doc, SCHEMAS['rltp-delivery-document.schema.json'], SCHEMAS['rltp-delivery-document.schema.json']).length === 0 &&
|
|
136
|
+
calOK(doc.issuedAt);
|
|
137
|
+
const failed = (reason, stage, extra = {}) => ({ kind: 'failed', result: { disposition: 'failed', reason, stage, ...extra } });
|
|
138
|
+
/** The tuple whose own rkid is `rkid`, with its relationship. */
|
|
139
|
+
export function tupleByRkid(state, rkid) {
|
|
140
|
+
for (const id of Object.keys(state.relationships).sort()) {
|
|
141
|
+
const rel = state.relationships[id];
|
|
142
|
+
for (const tuple of rel.tuples)
|
|
143
|
+
if (tuple.rkid === rkid)
|
|
144
|
+
return { rel, tuple };
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
/** The arrival channel's ack key (4.2): X25519 of the own key behind
|
|
149
|
+
* `rkid` and the counterpart key, HKDF under issuer/recipient. */
|
|
150
|
+
async function ackKey(ctx, rkid, counterpartKeyAgreement, issuer, recipient) {
|
|
151
|
+
const raw = xRawOfMk(counterpartKeyAgreement);
|
|
152
|
+
if (!raw)
|
|
153
|
+
return null;
|
|
154
|
+
const a = await ctx.keys.agree(rkid, raw, ctx.release);
|
|
155
|
+
if (a.status !== 'available')
|
|
156
|
+
return null;
|
|
157
|
+
try {
|
|
158
|
+
return await ackKeyOf(a.shared, issuer, recipient, ctx.crypto.subtle);
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Stages 1–8 against the preparation's snapshot. Never throws for
|
|
166
|
+
* anything the envelope carries; port failures surface as InfraError.
|
|
167
|
+
*/
|
|
168
|
+
export async function prepareReceive(ctx, env, tasks) {
|
|
169
|
+
const S = ctx.crypto.subtle;
|
|
170
|
+
const state = ctx.snapshot;
|
|
171
|
+
// 1–4
|
|
172
|
+
const agree = (rkid, epk) => ctx.keys.agree(rkid, epk, ctx.release);
|
|
173
|
+
const r = await receiveByAgreement(env, agree, (d) => Object.hasOwn(state.effects, d), S);
|
|
174
|
+
if (r.disposition === 'duplicate-known')
|
|
175
|
+
return { kind: 'duplicate', digest: r.digest };
|
|
176
|
+
if (r.disposition !== 'unique') {
|
|
177
|
+
const stage = r.stages[r.stages.length - 1].stage;
|
|
178
|
+
const reason = r.disposition.slice('failed('.length, -1);
|
|
179
|
+
return failed(reason, stage, r.key ? { key: r.key } : {});
|
|
180
|
+
}
|
|
181
|
+
const doc = r.document;
|
|
182
|
+
const digest = r.digest;
|
|
183
|
+
const rkid = env.rkid;
|
|
184
|
+
// 5 — profile, then recipient = own anchor under the arrival key's label
|
|
185
|
+
if (!profileOk(doc))
|
|
186
|
+
return failed('malformed', 5, { digest });
|
|
187
|
+
const release = ctx.release(rkid);
|
|
188
|
+
if (release.status !== 'live')
|
|
189
|
+
throw new InfraError('key-provider', 'agree answered for an rkid the release does not hold live');
|
|
190
|
+
const own = await ctx.keys.anchorOf(release.label);
|
|
191
|
+
if (doc.recipient !== own.anchor)
|
|
192
|
+
return failed('wrong-recipient', 5, { digest });
|
|
193
|
+
const at = tupleByRkid(state, rkid);
|
|
194
|
+
// 6 — the built-in ack path, in the form the acked document's class selects
|
|
195
|
+
if (doc.type === ACK_TYPE) {
|
|
196
|
+
const signed = ackProofForm(doc) === 'signed';
|
|
197
|
+
const f = signed ? signedAckForm(doc) : macAckForm(doc);
|
|
198
|
+
if (!f.ok)
|
|
199
|
+
return failed(f.reason, f.stage, { digest });
|
|
200
|
+
// 8 — consistency against what this holder sent (4.2): the document on
|
|
201
|
+
// that thread, sent from the arrival rkid, of the class the proof form
|
|
202
|
+
// claims; the issuer its recipient (the tuple's counterpart, or the
|
|
203
|
+
// anchor it went to where no tuple carried it)
|
|
204
|
+
// the ref in either rendering (u or z, 4.2) names the outbox item by its digest bytes
|
|
205
|
+
const ref = toU(f.ref) ?? f.ref;
|
|
206
|
+
const item = Object.hasOwn(state.outbox, ref) ? state.outbox[ref] : undefined;
|
|
207
|
+
if (!item || item.threadId !== f.threadId || item.recipient.rkid !== rkid || SIGNATURE_CLASS.has(item.type) !== signed)
|
|
208
|
+
return failed('validation-failed', 8, { digest });
|
|
209
|
+
const expected = at ? at.tuple.counterpartAnchor : item.recipient.anchor;
|
|
210
|
+
if (expected === undefined || doc.issuer !== expected)
|
|
211
|
+
return failed('validation-failed', 8, { digest });
|
|
212
|
+
if (signed) {
|
|
213
|
+
if (!(await diVerify(doc, doc.issuer, S)))
|
|
214
|
+
return failed('validation-failed', 8, { digest });
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
const key = await ackKey(ctx, rkid, item.recipient.keyAgreement, doc.issuer, doc.recipient);
|
|
218
|
+
if (!key || !(await macAckValid(doc, key, S)))
|
|
219
|
+
return failed('validation-failed', 8, { digest });
|
|
220
|
+
}
|
|
221
|
+
return { kind: 'ack', digest, ref };
|
|
222
|
+
}
|
|
223
|
+
// 6 — the task register, by the full type URI (no prefix, no fallback)
|
|
224
|
+
const h = tasks.get(doc.type);
|
|
225
|
+
if (!h)
|
|
226
|
+
return failed('unknown-type', 6, { digest });
|
|
227
|
+
if ((h.proof === 'absent') !== (doc.proof === undefined))
|
|
228
|
+
return failed('validation-failed', 6, { digest });
|
|
229
|
+
// 7–8 — decode, the closed acceptance binding, the handler's preparation
|
|
230
|
+
const payload = h.decode(doc.payload);
|
|
231
|
+
const refused = (r, stage) => failed(r.reason, stage, { digest, ...(r.ref !== undefined ? { ref: r.ref } : {}) });
|
|
232
|
+
if (isTaskRefusal(payload))
|
|
233
|
+
return refused(payload, payload.reason === 'malformed' ? 7 : 8);
|
|
234
|
+
const rdoc = Object.freeze({ ...doc, payload });
|
|
235
|
+
// the binding: the arrival tuple (4.4), or the handler's own channel
|
|
236
|
+
// where its document may arrive before any tuple (4.1, Membership)
|
|
237
|
+
let peer;
|
|
238
|
+
if (h.channel) {
|
|
239
|
+
const c = h.channel(state, rdoc, rkid);
|
|
240
|
+
if (isTaskRefusal(c))
|
|
241
|
+
return refused(c, c.reason === 'malformed' ? 7 : 8);
|
|
242
|
+
peer = c;
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
if (!at || doc.issuer !== at.tuple.counterpartAnchor)
|
|
246
|
+
return failed('validation-failed', 8, { digest });
|
|
247
|
+
// a deactivated tuple takes nothing new (6190, 6240): the arrival tuple is
|
|
248
|
+
// the active head of a live relationship, unless the handler binds its
|
|
249
|
+
// artifacts to the tuples an act pinned before a chaining (8270)
|
|
250
|
+
if (!h.pinned && (!liveRel(at.rel) || at.rel.activeHead !== at.tuple.ownPairLabel))
|
|
251
|
+
return failed('validation-failed', 8, { digest, ref: 'RLTP-TRU-6240' });
|
|
252
|
+
// the entry the arrival's relationship sends under (2146), by its current id
|
|
253
|
+
peer = { keyAgreement: at.tuple.counterpartKeyAgreement, contactId: entryOf(state, at.rel)?.id ?? at.rel.contactId };
|
|
254
|
+
}
|
|
255
|
+
const arrival = Object.freeze({ rkid, threadId: doc.threadId, digest, when: ctx.when });
|
|
256
|
+
const value = h.prepare ? await h.prepare(ctx, rdoc, arrival) : undefined;
|
|
257
|
+
if (isTaskRefusal(value))
|
|
258
|
+
return refused(value, 8);
|
|
259
|
+
// the ack, sealed before the transaction (4.2: created inside the
|
|
260
|
+
// effect's transaction — it commits with the cache entry or not at all),
|
|
261
|
+
// in the form the document's class selects (4.4)
|
|
262
|
+
const base = ackDocument({
|
|
263
|
+
id: ctx.entropy.id('ack.id'), issuer: own.anchor, recipient: doc.issuer,
|
|
264
|
+
threadId: arrival.threadId, issuedAt: iso(ctx.when), ref: digest,
|
|
265
|
+
});
|
|
266
|
+
let ackDoc;
|
|
267
|
+
if (SIGNATURE_CLASS.has(doc.type)) {
|
|
268
|
+
ackDoc = await diSignWith(own.anchor, (b) => ctx.keys.sign(release.label, b), base, base.issuedAt, S);
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
const key = await ackKey(ctx, rkid, peer.keyAgreement, own.anchor, doc.issuer);
|
|
272
|
+
if (!key)
|
|
273
|
+
return failed('validation-failed', 8, { digest });
|
|
274
|
+
ackDoc = await macAck(base, key, S);
|
|
275
|
+
}
|
|
276
|
+
const envelope = await seal(ackDoc, peer.keyAgreement, { ephSeed: ctx.entropy.bytes('seal.eph', 32), nonce: ctx.entropy.bytes('seal.nonce', 12) }, S);
|
|
277
|
+
const ack = {
|
|
278
|
+
digest: await digestDoc(ackDoc, S), envelope, threadId: arrival.threadId,
|
|
279
|
+
recipient: { contactId: peer.contactId, rkid, keyAgreement: peer.keyAgreement, ...(peer.via !== undefined ? { via: peer.via } : {}) },
|
|
280
|
+
};
|
|
281
|
+
return { kind: 'task', digest, type: doc.type, doc: rdoc, arrival, value, ack };
|
|
282
|
+
}
|
|
283
|
+
/** The outbox after a valid ack of `ref` (4.2, 6.1): delivered, late after
|
|
284
|
+
* failed; unchanged when already delivered. Shared with report(). */
|
|
285
|
+
export function markDelivered(state, ref, when) {
|
|
286
|
+
const it = state.outbox[ref];
|
|
287
|
+
if (it.history.some((s) => s.status === 'delivered'))
|
|
288
|
+
return { outbox: state.outbox, event: null };
|
|
289
|
+
const late = triasOf(it) === 'failed';
|
|
290
|
+
const { nextAttemptAt: _, ...rest } = it;
|
|
291
|
+
return {
|
|
292
|
+
outbox: { ...state.outbox, [ref]: { ...rest, history: [...it.history, { status: 'delivered', at: when, late }] } },
|
|
293
|
+
event: { type: 'delivery.status', digest: ref, threadId: it.threadId, status: 'delivered', late },
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
/** Prepared for a handler: its own value under the receive's binding. */
|
|
297
|
+
export const handlerPrepared = (p, value) => Object.freeze({ value, version: p.version, commitSeq: p.commitSeq });
|
|
298
|
+
//# sourceMappingURL=receive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receive.js","sourceRoot":"","sources":["../src/receive.ts"],"names":[],"mappings":"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","sourcesContent":["// receive — the holder's receive core (lib Stage 2, note §4.3; Delivery\n// §6.2, §4.2, §4.4). The engine runs it as its built-in `receive`: the\n// preparation (async) walks stages 1–8, the transition (sync) is stage 9.\n//\n// 1–4 once, here, through delivery.receiveByAgreement: the key agreement\n// is the KeyProvider's `agree` under the engine's release from\n// `addresses` (a tombstone answers retired: stage 3; an rkid never\n// issued answers unknown: stage 2); the completed-effect cache is\n// `state.effects`\n// 5 the document profile (schema, calendar-valid issuedAt) and\n// recipient = the own anchor of the label the arrival rkid derives\n// under (addresses)\n// 6 dispatch by the full type URI with version: the built-in\n// delivery-ack path, else the task register, else unknown-type;\n// then the entry's proof declaration. Delivery §3 wants `proof`\n// absent on every type but delivery-ack and registry-declaration,\n// and §4.4 puts the declaration into the registry entry; the\n// profile schema can name only the types it knows, so for\n// companion types the rule is enforced here, the earliest stage at\n// which the receiver holds the entry: a mismatch is\n// failed(validation-failed)\n// 7–8 the handler's decode (malformed at 7, any other refusal at 8),\n// the core's closed acceptance binding (Delivery 4.4: the arrival\n// tuple is selected by rkid, the document's issuer is its\n// counterpart anchor), the handler's prepare, and the ack: sealed\n// here, before the transaction, from fresh entropy\n// 9 the handler's apply; the core files the effect-cache entry with\n// the ack in the same commit (the handler never writes `effects`)\n// and hands the ack out first among the outbound\n//\n// Acks (delivery-ack/0.1) are no registered task: one common path checks\n// the form (ack.ts macAckForm), then the consistency of 4.2 against the\n// outbox — `ref` is a document this holder sent on that thread, on the\n// arrival tuple (outbox item rkid = arrival rkid), the issuer is that\n// tuple's counterpart, the referenced document's type is of the\n// designated-verifier class (a MAC ack of a signature-class document is\n// the wrong class), and the MAC verifies under the arrival tuple's ack\n// key. A valid ack marks the item delivered (late after failed) and\n// earns a terminal cache entry, no ack of its own.\n//\n// The stage-9 lock set (Delivery 6.2): the engine serializes every\n// operation of a holder in one queue and commits by CAS — a strictly\n// stronger serialization than the lock set asks for (it holds every key\n// of the holder, not only the overlapping ones), which is how this\n// library implements it under Stage 2's one-writer contract. The lock set\n// — the digest, and for star and group-star chunks additionally the\n// assembly key (tuple, type, salt) of 4.4 — is held for the whole\n// evaluation; a CAS conflict re-reads and re-enters at stage 1, which\n// re-checks the cache at stage 4. The chunk types (trust/star.ts,\n// trust/group-star.ts, PR 4b) need no key of their own here: every\n// chunk of one tuple and type is evaluated against, and committed over,\n// the one state version its preparation read, so the completing chunk's\n// effect (validated assembly, accepted snapshot, completed-salt advance)\n// commits with the cache entry and the ack in one transaction.\n//\n// A refusal (TaskRefusal) never commits anything, at any stage.\n//\n// A handler's apply may answer a TaskDiscarded: the receiver discarded an\n// open assembly and holds its salt as the lower bound (5366), for one of\n// two reasons: `resource-limit` (Trust 5365), or `rejected` — an\n// authenticated chunk (its MAC verified) violates the assembly rules\n// (5260–5310, 5500, 5510), and the spec rejects the whole delivery, so it\n// must not complete from any later chunk. That is a spec-mandated state\n// effect, not a failure of the document: its state commits and the result\n// is the disposition `discarded` with the reason and the rule — no\n// effect-cache entry (a redelivery is evaluated afresh and meets the lower\n// bound), no ack (the delivery must not complete), no event; the completed\n// high-water mark stays. A chunk that does not authenticate is a plain\n// refusal and touches nothing. DELIVERY GAP: Delivery §6.2 names no\n// disposition for a document whose processing ends in such a discard;\n// `discarded` (both reasons) is this library's, to be registered in\n// Delivery 0.82.\n//\n// A verified ack runs the ack handler a module registered for the\n// acknowledged item's type, in the ack's transaction (engine.ts\n// AckHandler): the sender side of 5660, completion by verified acks only.\n//\n// Ack class (4.4): the class follows the payload's audience class. The\n// types of SIGNATURE_CLASS carry transferable signatures (the encounter\n// carriers, the membership documents, the signed introduction artifacts,\n// the registry declaration): their ack is SIGNED, an eddsa-jcs-2022 proof\n// under the ack's issuer anchor through the KeyProvider (`sign` with the\n// arrival key's label). Every other type is designated-verifier and earns\n// the MAC form under the channel ack key of the arrival rkid and the\n// counterpart key. A received ack is checked in the form its referenced\n// outbox item's class selects; the other form is validation-failed.\n//\n// The acceptance binding before a tuple exists (PR 7): a handler with a\n// `channel` binds its document itself, from the document, where it may\n// arrive on an own key no tuple carries yet — the encounter bundle on the\n// displayed card's key (Delivery 4.1: the bundle establishes the tuple,\n// its issuer bound to card.anchor = credential.issuer), the membership\n// documents on member keys (Membership 3.1, 3.2). `channel` names the\n// counterpart's key agreement the ack is sealed to and the contact it is\n// filed under, or refuses (stage 7 for malformed, else 8). Every other\n// handler keeps the tuple binding of Delivery 4.4.\nimport { calOK, iso, makeValidator, toU } from './core.js'\nimport type { Json } from './core.js'\nimport { diSignWith, diVerify, digestDoc, xRawOfMk } from './crypto.js'\nimport { receiveByAgreement, seal } from './delivery.js'\nimport type { KeyAnswer } from './delivery.js'\nimport { ACK_TYPE, ackDocument, ackKeyOf, ackProofForm, macAck, macAckForm, macAckValid, signedAckForm } from './ack.js'\nimport { SCHEMAS } from './schemas.js'\nimport { triasOf } from './state.js'\nimport { entryOf, liveRel } from './trust/state.js'\nimport type { HolderState, Millis, OutboxItem, Relationship, StoredAck, Tuple } from './state.js'\n\n/** An ack as sealed in the preparation; the engine adds its schedule. */\nexport type SealedAck = Pick<StoredAck, 'digest' | 'envelope' | 'threadId' | 'recipient'>\nimport type { Outbound } from './ports.js'\nimport { InfraError } from './results.js'\nimport type { ReceiveFailure, ReceiveResult, ReceiveStageNo } from './results.js'\nimport type { EventDraft, PrepareCtx, Prepared } from './engine.js'\n\n// ── the task handler contract ──────────────────────────────────────────\n\n/** Where and when a document arrived: the own rkid it was sealed to, its\n * thread, its digest and the receive's `when`. */\nexport interface Arrival { rkid: string, threadId: string, digest: string, when: Millis }\n\n/** Why a task handler refuses a document; the stage follows from where:\n * decode 'malformed' → 7, decode or prepare otherwise → 8, apply → 9. */\nexport type TaskFailure = 'malformed' | 'validation-failed' | 'stale-issuance' | 'gate-future' | 'consumed-challenge'\n\n/** A handler's refusal: nothing commits, the digest stays uncached and\n * a redelivery is evaluated afresh (Delivery 6.2 stage 4) — with one\n * narrow, enumerated exception, the Encounter aging latch: an apply that\n * refuses because its authoritative resolution found an own challenge past\n * its age bound (Encounter 5260, 5270, 5290; Delivery 4.1 check 5) returns\n * `latch`, the state with that challenge removed, and the engine commits\n * exactly it (and the raised lastWhen): no cache entry, no ack, no event;\n * the disposition stays failed. A latch that touches anything beyond\n * encounter.challenges is a programming error and throws (engine.ts). */\nexport interface TaskRefusal { ok: false, reason: TaskFailure, ref?: string, latch?: HolderState }\n\n/** A discard at a resource limit (Trust 5365/5366), answered by apply:\n * `state` commits (assembly dropped, lower bound held), the disposition\n * is `discarded`, with no cache entry, no ack and no event. */\nexport interface TaskDiscarded { discarded: true, reason: DiscardReason, state: HolderState, ref?: string }\n\n/** Why an assembly was discarded: a local resource limit (5365), or an\n * authenticated violation of the assembly rules that rejects the delivery. */\nexport type DiscardReason = 'resource-limit' | 'rejected'\n\nexport const isTaskDiscarded = (x: unknown): x is TaskDiscarded =>\n x !== null && typeof x === 'object' && (x as TaskDiscarded).discarded === true\n\n/** A received document after stage 7: the profile fields, its payload\n * as the handler's decode returned it. Read-only. */\nexport interface ReceivedDocument<T = unknown> {\n readonly id: string\n readonly type: string\n readonly issuer: string\n readonly recipient: string\n readonly threadId: string\n readonly issuedAt: string\n readonly payload: T\n readonly ceremony?: Json\n readonly proof?: Json\n}\n\n/** A sealed ack as the outbound the app sends, at the given attempt. */\nexport const ackOutbound = (a: Readonly<SealedAck>, attempt: number): Outbound =>\n structuredClone({ digest: a.digest, envelope: a.envelope, type: ACK_TYPE, threadId: a.threadId, recipient: a.recipient, attempt })\n\nconst TT = 'https://real-life.org/trust-tasks/'\n/** Signature-class types (Delivery 4.2/4.4): payloads whose authenticity\n * is a transferable signature; their acks are signed, not MACed. The\n * `x-` slugs are this library's own experimental, unregistered forms\n * for what the specifications leave to the application (the membership\n * prelude, Membership 1.2; the welcome until the Access envelope is\n * built; the introduction offer that conveys the target designator,\n * Trust 8.3): signed documents as well. A receiver that does not know\n * them answers unknown-type (Delivery §6.2). */\nexport const SIGNATURE_CLASS: ReadonlySet<string> = new Set([\n TT + 'encounter-bundle/0.1',\n TT + 'encounter-credential-delivery/0.1',\n TT + 'membership-invite/0.2',\n TT + 'membership-accept/0.2',\n TT + 'membership-evidence/0.1',\n TT + 'membership-evidence/0.2',\n TT + 'registry-declaration/0.1',\n TT + 'introduction-request/0.1',\n TT + 'introduction-forward/0.1',\n TT + 'introduction-reply/0.1',\n TT + 'x-membership-prelude-request/0.1',\n TT + 'x-membership-prelude-reply/0.1',\n TT + 'x-membership-welcome/0.1',\n TT + 'x-introduction-offer/0.1',\n])\n\n/** The counterpart a `channel` binding names: the key agreement the ack\n * is sealed to and the contact it is filed under. */\n/** The binding a document arrives under: the counterpart's key and the\n * contact; `via`, where the arrival key is no tuple's (a member key), the\n * own rkid of the tuple the contact was named through (Recipient.via). */\nexport interface Channel { keyAgreement: string, contactId: string, via?: string }\n\nexport const isTaskRefusal = (x: unknown): x is TaskRefusal =>\n x !== null && typeof x === 'object' && (x as TaskRefusal).ok === false && typeof (x as TaskRefusal).reason === 'string'\n\n// ── the plan a preparation hands to stage 9 ────────────────────────────\n\ntype Failed = Extract<ReceiveResult, { disposition: 'failed' }>\n\n/** What stages 1–8 decided, bound to the snapshot they ran against. */\nexport type ReceivePlan =\n | { kind: 'failed', result: Failed }\n | { kind: 'duplicate', digest: string }\n | { kind: 'ack', digest: string, ref: string }\n | { kind: 'task', digest: string, type: string, doc: ReceivedDocument, arrival: Arrival, value: unknown, ack: SealedAck }\n\n/** The handler surface the core needs (engine.ts TaskHandler). */\nexport interface TaskEntry {\n proof: 'absent' | 'required'\n decode (payload: unknown): unknown\n channel? (state: Readonly<HolderState>, doc: ReceivedDocument, rkid: string): Channel | TaskRefusal\n /** may arrive on a deactivated tuple an act pinned (engine TaskHandler) */\n pinned?: true\n prepare? (ctx: PrepareCtx, doc: ReceivedDocument, arrival: Arrival): Promise<unknown>\n}\n\nconst V = makeValidator(SCHEMAS)\nconst profileOk = (doc: unknown): boolean =>\n V.validate(doc, SCHEMAS['rltp-delivery-document.schema.json'], SCHEMAS['rltp-delivery-document.schema.json']).length === 0 &&\n calOK((doc as { issuedAt?: unknown }).issuedAt)\n\nconst failed = (reason: ReceiveFailure, stage: ReceiveStageNo, extra: { digest?: string, key?: 'unknown' | 'retired', ref?: string } = {}): ReceivePlan =>\n ({ kind: 'failed', result: { disposition: 'failed', reason, stage, ...extra } })\n\n/** The tuple whose own rkid is `rkid`, with its relationship. */\nexport function tupleByRkid (state: Readonly<HolderState>, rkid: string): { rel: Relationship, tuple: Tuple } | null {\n for (const id of Object.keys(state.relationships).sort()) {\n const rel = state.relationships[id]\n for (const tuple of rel.tuples) if (tuple.rkid === rkid) return { rel, tuple }\n }\n return null\n}\n\n/** The arrival channel's ack key (4.2): X25519 of the own key behind\n * `rkid` and the counterpart key, HKDF under issuer/recipient. */\nasync function ackKey (ctx: PrepareCtx, rkid: string, counterpartKeyAgreement: string, issuer: string, recipient: string): Promise<Uint8Array | null> {\n const raw = xRawOfMk(counterpartKeyAgreement)\n if (!raw) return null\n const a = await ctx.keys.agree(rkid, raw, ctx.release)\n if (a.status !== 'available') return null\n try { return await ackKeyOf(a.shared, issuer, recipient, ctx.crypto.subtle) } catch { return null }\n}\n\n/**\n * Stages 1–8 against the preparation's snapshot. Never throws for\n * anything the envelope carries; port failures surface as InfraError.\n */\nexport async function prepareReceive (ctx: PrepareCtx, env: unknown, tasks: ReadonlyMap<string, TaskEntry>): Promise<ReceivePlan> {\n const S = ctx.crypto.subtle\n const state = ctx.snapshot\n // 1–4\n const agree = (rkid: string, epk: Uint8Array): Promise<KeyAnswer> => ctx.keys.agree(rkid, epk, ctx.release)\n const r = await receiveByAgreement(env, agree, (d) => Object.hasOwn(state.effects, d), S)\n if (r.disposition === 'duplicate-known') return { kind: 'duplicate', digest: r.digest! }\n if (r.disposition !== 'unique') {\n const stage = r.stages[r.stages.length - 1].stage\n const reason = r.disposition.slice('failed('.length, -1) as ReceiveFailure\n return failed(reason, stage, r.key ? { key: r.key } : {})\n }\n const doc = r.document as Record<string, Json>\n const digest = r.digest!\n const rkid = (env as { rkid: string }).rkid\n // 5 — profile, then recipient = own anchor under the arrival key's label\n if (!profileOk(doc)) return failed('malformed', 5, { digest })\n const release = ctx.release(rkid)\n if (release.status !== 'live') throw new InfraError('key-provider', 'agree answered for an rkid the release does not hold live')\n const own = await ctx.keys.anchorOf(release.label)\n if (doc.recipient !== own.anchor) return failed('wrong-recipient', 5, { digest })\n const at = tupleByRkid(state, rkid)\n // 6 — the built-in ack path, in the form the acked document's class selects\n if (doc.type === ACK_TYPE) {\n const signed = ackProofForm(doc) === 'signed'\n const f = signed ? signedAckForm(doc) : macAckForm(doc)\n if (!f.ok) return failed(f.reason, f.stage, { digest })\n // 8 — consistency against what this holder sent (4.2): the document on\n // that thread, sent from the arrival rkid, of the class the proof form\n // claims; the issuer its recipient (the tuple's counterpart, or the\n // anchor it went to where no tuple carried it)\n // the ref in either rendering (u or z, 4.2) names the outbox item by its digest bytes\n const ref = toU(f.ref) ?? f.ref\n const item: OutboxItem | undefined = Object.hasOwn(state.outbox, ref) ? state.outbox[ref] : undefined\n if (!item || item.threadId !== f.threadId || item.recipient.rkid !== rkid || SIGNATURE_CLASS.has(item.type) !== signed) return failed('validation-failed', 8, { digest })\n const expected = at ? at.tuple.counterpartAnchor : item.recipient.anchor\n if (expected === undefined || doc.issuer !== expected) return failed('validation-failed', 8, { digest })\n if (signed) {\n if (!(await diVerify(doc, doc.issuer as string, S))) return failed('validation-failed', 8, { digest })\n } else {\n const key = await ackKey(ctx, rkid, item.recipient.keyAgreement, doc.issuer as string, doc.recipient as string)\n if (!key || !(await macAckValid(doc, key, S))) return failed('validation-failed', 8, { digest })\n }\n return { kind: 'ack', digest, ref }\n }\n // 6 — the task register, by the full type URI (no prefix, no fallback)\n const h = tasks.get(doc.type as string)\n if (!h) return failed('unknown-type', 6, { digest })\n if ((h.proof === 'absent') !== (doc.proof === undefined)) return failed('validation-failed', 6, { digest })\n // 7–8 — decode, the closed acceptance binding, the handler's preparation\n const payload = h.decode(doc.payload)\n const refused = (r: TaskRefusal, stage: ReceiveStageNo): ReceivePlan => failed(r.reason, stage, { digest, ...(r.ref !== undefined ? { ref: r.ref } : {}) })\n if (isTaskRefusal(payload)) return refused(payload, payload.reason === 'malformed' ? 7 : 8)\n const rdoc = Object.freeze({ ...doc, payload }) as ReceivedDocument\n // the binding: the arrival tuple (4.4), or the handler's own channel\n // where its document may arrive before any tuple (4.1, Membership)\n let peer: Channel\n if (h.channel) {\n const c = h.channel(state, rdoc, rkid)\n if (isTaskRefusal(c)) return refused(c, c.reason === 'malformed' ? 7 : 8)\n peer = c\n } else {\n if (!at || doc.issuer !== at.tuple.counterpartAnchor) return failed('validation-failed', 8, { digest })\n // a deactivated tuple takes nothing new (6190, 6240): the arrival tuple is\n // the active head of a live relationship, unless the handler binds its\n // artifacts to the tuples an act pinned before a chaining (8270)\n if (!h.pinned && (!liveRel(at.rel) || at.rel.activeHead !== at.tuple.ownPairLabel)) return failed('validation-failed', 8, { digest, ref: 'RLTP-TRU-6240' })\n // the entry the arrival's relationship sends under (2146), by its current id\n peer = { keyAgreement: at.tuple.counterpartKeyAgreement, contactId: entryOf(state, at.rel)?.id ?? at.rel.contactId }\n }\n const arrival: Arrival = Object.freeze({ rkid, threadId: doc.threadId as string, digest, when: ctx.when })\n const value = h.prepare ? await h.prepare(ctx, rdoc, arrival) : undefined\n if (isTaskRefusal(value)) return refused(value, 8)\n // the ack, sealed before the transaction (4.2: created inside the\n // effect's transaction — it commits with the cache entry or not at all),\n // in the form the document's class selects (4.4)\n const base = ackDocument({\n id: ctx.entropy.id('ack.id'), issuer: own.anchor, recipient: doc.issuer as string,\n threadId: arrival.threadId, issuedAt: iso(ctx.when), ref: digest,\n })\n let ackDoc: Json\n if (SIGNATURE_CLASS.has(doc.type as string)) {\n ackDoc = await diSignWith(own.anchor, (b) => ctx.keys.sign(release.label, b), base as unknown as Record<string, Json>, base.issuedAt, S) as unknown as Json\n } else {\n const key = await ackKey(ctx, rkid, peer.keyAgreement, own.anchor, doc.issuer as string)\n if (!key) return failed('validation-failed', 8, { digest })\n ackDoc = await macAck(base, key, S) as unknown as Json\n }\n const envelope = await seal(ackDoc, peer.keyAgreement, { ephSeed: ctx.entropy.bytes('seal.eph', 32), nonce: ctx.entropy.bytes('seal.nonce', 12) }, S)\n const ack: SealedAck = {\n digest: await digestDoc(ackDoc, S), envelope, threadId: arrival.threadId,\n recipient: { contactId: peer.contactId, rkid, keyAgreement: peer.keyAgreement, ...(peer.via !== undefined ? { via: peer.via } : {}) },\n }\n return { kind: 'task', digest, type: doc.type as string, doc: rdoc, arrival, value, ack }\n}\n\n/** The outbox after a valid ack of `ref` (4.2, 6.1): delivered, late after\n * failed; unchanged when already delivered. Shared with report(). */\nexport function markDelivered (state: Readonly<HolderState>, ref: string, when: Millis): { outbox: HolderState['outbox'], event: EventDraft | null } {\n const it = state.outbox[ref]\n if (it.history.some((s) => s.status === 'delivered')) return { outbox: state.outbox, event: null }\n const late = triasOf(it) === 'failed'\n const { nextAttemptAt: _, ...rest } = it\n return {\n outbox: { ...state.outbox, [ref]: { ...rest, history: [...it.history, { status: 'delivered', at: when, late }] } },\n event: { type: 'delivery.status', digest: ref, threadId: it.threadId, status: 'delivered', late },\n }\n}\n\n/** Prepared for a handler: its own value under the receive's binding. */\nexport const handlerPrepared = <P>(p: Prepared<unknown>, value: P): Prepared<P> =>\n Object.freeze({ value, version: p.version, commitSeq: p.commitSeq })\n"]}
|