@real-life/trust-protocol 0.3.2 → 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 +56 -10
- 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 -62
- package/dist/probe/introduce.d.ts.map +0 -1
- package/dist/probe/introduce.js +0 -306
- package/dist/probe/introduce.js.map +0 -1
- package/dist/probe/membership.d.ts +0 -96
- package/dist/probe/membership.d.ts.map +0 -1
- package/dist/probe/membership.js +0 -467
- 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/views.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
// views — what an app reads: pure projections of the holder's state
|
|
2
|
+
// (lib Stage 2, note §4.5).
|
|
3
|
+
//
|
|
4
|
+
// `state → View`, synchronous, without the engine: every function here
|
|
5
|
+
// reads one state and returns fresh, deep-frozen objects that share no
|
|
6
|
+
// reference with it, so a UI can keep them and the state stays untouched.
|
|
7
|
+
// Each view carries the commitSeq of the state it was read from; views of
|
|
8
|
+
// one snapshot belong together. The holder hands them out over its
|
|
9
|
+
// snapshot (holder-api.ts); after a `subscribe` announcement the app
|
|
10
|
+
// re-reads them. Views never write: whatever ages state (expiry, the
|
|
11
|
+
// encounter's aging latch) is an act, never a read.
|
|
12
|
+
//
|
|
13
|
+
// Rule numbers: bare four-digit numbers are RLTP-TRU (trust-layer.md).
|
|
14
|
+
//
|
|
15
|
+
// Choices this file makes where the note leaves them open:
|
|
16
|
+
// - contacts are listed in entry-commit order (2120); entries without a
|
|
17
|
+
// position (2060) follow, by id. A contact is found by its entry id or
|
|
18
|
+
// by any of its aliases (2140)
|
|
19
|
+
// - provenance and via come from the contact's oldest relationship (by
|
|
20
|
+
// its provenance time, then id): how the person came, not how often
|
|
21
|
+
// - tuples belong to the entry their entryId names (2145): an entry's
|
|
22
|
+
// tuples are those whose entryId is its id or one of its aliases, over
|
|
23
|
+
// its own relationships and any relationship that stands behind two
|
|
24
|
+
// entries. Its heads are the active-head tuples among them of live
|
|
25
|
+
// relationships (not chained into another), not deactivated; under
|
|
26
|
+
// 2146 the appended tuple's entry takes the chain's active head
|
|
27
|
+
// - verification is the edge of Encounter 4.2 over all of the entry's
|
|
28
|
+
// tuples, deactivated and older ones included (historical evidence;
|
|
29
|
+
// one edge per relationship, carried along its chain): `outgoing` an
|
|
30
|
+
// own step credential was issued, `incoming` the counterparty's was
|
|
31
|
+
// accepted (5.6), `mutual` both, `met` neither — read from the
|
|
32
|
+
// enactment records of those tuples (encounter/ceremony.ts). An entry
|
|
33
|
+
// with no record at all (built without a ceremony: introduced, or a
|
|
34
|
+
// test state) reads the anchor mappings instead: `outgoing` one was
|
|
35
|
+
// issued (mappingOut), `incoming` one was verified (mappingIn)
|
|
36
|
+
// - displayName: the profile's name (6425), else the self-declared name
|
|
37
|
+
// on the counterparty card of the entry's newest record (Encounter
|
|
38
|
+
// 6120: the app binds its own local name to the anchor)
|
|
39
|
+
// - trust.given is the anchor mapping class on (the Trust act, 2770);
|
|
40
|
+
// trust.received a verified anchor mapping from the contact, whose
|
|
41
|
+
// class has no default recipient (2760); trust.paused the pause of 5.4,
|
|
42
|
+
// star and blinded group star both `off` (2780); trust.pending: given,
|
|
43
|
+
// but not yet out on every head (no mapping issued on it, or its
|
|
44
|
+
// relationship lags (6595)), or a re-issue or class-on duty for the
|
|
45
|
+
// anchor mapping is open at a version this library handles (a duty of
|
|
46
|
+
// an unhandled version is opaque, note §2.1). Delivery of the documents is not part of
|
|
47
|
+
// it; deliveryStatus answers that
|
|
48
|
+
// - classes give the setting and whether the class is on toward the
|
|
49
|
+
// contact (2760, 2840); the sealed group star also per group (2830):
|
|
50
|
+
// every group of the holder and every group the contact holds a
|
|
51
|
+
// per-group setting for, by id, with the setting (`default` where none
|
|
52
|
+
// is held) and whether it is on for (group, contact) — the per-group
|
|
53
|
+
// setting first, else the class (trust/group-star.ts sealedOn)
|
|
54
|
+
// - sharedGroups: the union of the groups the last accepted group star
|
|
55
|
+
// on each of the entry's heads hit (5520, trust/group-star.ts), lagging
|
|
56
|
+
// heads included (the group star travels on them, 6595); undefined
|
|
57
|
+
// where no head ever accepted one
|
|
58
|
+
// - a contact's profile (6425): among the verified profile@1 bodies
|
|
59
|
+
// (6b.2) on its heads whose relationship does not lag (6461, 6595),
|
|
60
|
+
// the highest revision, among equal ones the one verified last
|
|
61
|
+
// (highest verifiedSeq); displayName is that profile's name
|
|
62
|
+
// - deliveryStatus(x) lists the outbox items whose digest or threadId is
|
|
63
|
+
// x, by first submission, then digest; an unknown x lists none
|
|
64
|
+
// - relationships: the entry's own (relIds), in that order; chainedFrom
|
|
65
|
+
// the husks chained into each (chainedInto), by id
|
|
66
|
+
// - a contact without a relationship breaks an invariant and throws
|
|
67
|
+
import { freezeDeep } from './util-freeze.js';
|
|
68
|
+
import { triasOf } from './state.js';
|
|
69
|
+
import { CLASSES, activeTuple, classOn, findContact, lags, trusted as isTrusted } from './trust/state.js';
|
|
70
|
+
import { sealedOn } from './trust/group-star.js';
|
|
71
|
+
import { classOfDuty } from './trust/duties.js';
|
|
72
|
+
// ── helpers ────────────────────────────────────────────────────────────
|
|
73
|
+
const cmp = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
|
|
74
|
+
const cmpDec = (a, b) => { const x = BigInt(a), y = BigInt(b); return x < y ? -1 : x > y ? 1 : 0; };
|
|
75
|
+
const isObj = (x) => x !== null && typeof x === 'object' && !Array.isArray(x);
|
|
76
|
+
/** The string fields of a profile body that a view shows. */
|
|
77
|
+
const profileFields = (body) => {
|
|
78
|
+
const out = {};
|
|
79
|
+
if (!isObj(body))
|
|
80
|
+
return out;
|
|
81
|
+
for (const k of ['name', 'image', 'text'])
|
|
82
|
+
if (typeof body[k] === 'string')
|
|
83
|
+
out[k] = body[k];
|
|
84
|
+
return out;
|
|
85
|
+
};
|
|
86
|
+
const recordIndex = (state) => {
|
|
87
|
+
const ix = new Map();
|
|
88
|
+
for (const r of Object.values(state.encounter.records))
|
|
89
|
+
ix.set(r.label, r);
|
|
90
|
+
return ix;
|
|
91
|
+
};
|
|
92
|
+
const entryIndex = (state) => {
|
|
93
|
+
const ix = new Map();
|
|
94
|
+
for (const r of Object.values(state.relationships)) {
|
|
95
|
+
for (const t of r.tuples) {
|
|
96
|
+
let s = ix.get(t.entryId);
|
|
97
|
+
if (!s)
|
|
98
|
+
ix.set(t.entryId, (s = new Set()));
|
|
99
|
+
s.add(r.id);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return ix;
|
|
103
|
+
};
|
|
104
|
+
/** The contact's own relationships, then those holding a tuple of its entry. */
|
|
105
|
+
const relationshipsOf = (state, c, ids, ix) => {
|
|
106
|
+
const own = c.relIds.filter((id) => Object.hasOwn(state.relationships, id)).map((id) => state.relationships[id]);
|
|
107
|
+
if (!own.length)
|
|
108
|
+
throw new Error(`views: contact ${c.id} has no relationship`);
|
|
109
|
+
const seen = new Set(own.map((r) => r.id));
|
|
110
|
+
const all = [...own];
|
|
111
|
+
for (const id of ids) {
|
|
112
|
+
for (const rid of ix.get(id) ?? []) {
|
|
113
|
+
if (!seen.has(rid)) {
|
|
114
|
+
seen.add(rid);
|
|
115
|
+
all.push(state.relationships[rid]);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return { own, all };
|
|
120
|
+
};
|
|
121
|
+
const project = (state, c, ix, rix) => {
|
|
122
|
+
const ids = new Set([c.id, ...c.aliases]);
|
|
123
|
+
const { own, all: rels } = relationshipsOf(state, c, ids, ix);
|
|
124
|
+
const mine = (t) => ids.has(t.entryId);
|
|
125
|
+
const tuples = rels.flatMap((r) => r.tuples.filter(mine));
|
|
126
|
+
const origin = [...own].sort((a, b) => (a.provenance.at - b.provenance.at) || cmp(a.id, b.id))[0];
|
|
127
|
+
const records = tuples.map((t) => rix.get(t.ownPairLabel)).filter((r) => r !== undefined);
|
|
128
|
+
const out = records.length ? records.some((r) => r.out !== null) : tuples.some((t) => t.mappingOut.body !== null);
|
|
129
|
+
const inn = records.length ? records.some((r) => r.in !== null) : tuples.some((t) => t.mappingIn.body !== null);
|
|
130
|
+
const newest = [...records].sort((a, b) => b.at - a.at)[0];
|
|
131
|
+
const introduced = own.map((r) => r.memory.introducedName).find((n) => typeof n === 'string');
|
|
132
|
+
const cardName = typeof newest?.card?.name === 'string' ? newest.card.name : introduced;
|
|
133
|
+
const trusted = isTrusted(c);
|
|
134
|
+
const classes = {};
|
|
135
|
+
for (const cls of CLASSES)
|
|
136
|
+
classes[cls] = { setting: c.settings[cls], on: classOn(cls, c.settings[cls], trusted) };
|
|
137
|
+
const groups = {};
|
|
138
|
+
for (const g of [...new Set([...Object.keys(state.groups), ...Object.keys(c.groupSettings)])].sort(cmp)) {
|
|
139
|
+
groups[g] = { setting: Object.hasOwn(c.groupSettings, g) ? c.groupSettings[g] : 'default', on: sealedOn(c, g) };
|
|
140
|
+
}
|
|
141
|
+
const heads = [];
|
|
142
|
+
for (const r of rels) {
|
|
143
|
+
if (r.chainedInto !== null)
|
|
144
|
+
continue;
|
|
145
|
+
const t = activeTuple(r);
|
|
146
|
+
if (t && !t.deactivated && mine(t))
|
|
147
|
+
heads.push({ r, t, lagging: lags(r, rels) });
|
|
148
|
+
}
|
|
149
|
+
// a class-on or re-issue of the anchor mapping, at a version this library
|
|
150
|
+
// handles (classOfDuty: an unhandled version is opaque and owes nothing here)
|
|
151
|
+
const owed = Object.values(state.duties).some((d) => classOfDuty(d) === 'anchorMapping' && d.contactId === c.id);
|
|
152
|
+
const pending = trusted && (owed || heads.some((h) => h.t.mappingOut.body === null || h.lagging));
|
|
153
|
+
let best;
|
|
154
|
+
for (const { t, lagging } of heads) {
|
|
155
|
+
if (lagging || t.profileIn.body === null)
|
|
156
|
+
continue;
|
|
157
|
+
if (!best || cmpDec(t.profileIn.rev, best.profileIn.rev) > 0 ||
|
|
158
|
+
(cmpDec(t.profileIn.rev, best.profileIn.rev) === 0 && cmpDec(t.profileIn.verifiedSeq, best.profileIn.verifiedSeq) > 0))
|
|
159
|
+
best = t;
|
|
160
|
+
}
|
|
161
|
+
const profile = best ? { revision: best.profileIn.rev, ...profileFields(best.profileIn.body) } : undefined;
|
|
162
|
+
const received = heads.map((h) => h.t.groupStarIn.accepted).filter((a) => a !== null);
|
|
163
|
+
const sharedGroups = received.length ? [...new Set(received.flatMap((a) => a.groups))].sort(cmp) : undefined;
|
|
164
|
+
return {
|
|
165
|
+
commitSeq: state.commitSeq,
|
|
166
|
+
id: c.id,
|
|
167
|
+
aliases: [...c.aliases],
|
|
168
|
+
relationships: own.map((r) => ({
|
|
169
|
+
id: r.id, tuples: r.tuples.length,
|
|
170
|
+
chainedFrom: Object.values(state.relationships).filter((x) => x.chainedInto === r.id).map((x) => x.id).sort(cmp),
|
|
171
|
+
})),
|
|
172
|
+
...(profile?.name !== undefined ? { displayName: profile.name } : cardName !== undefined ? { displayName: cardName } : {}),
|
|
173
|
+
provenance: origin.provenance.kind,
|
|
174
|
+
...(origin.provenance.kind === 'introduced' && origin.provenance.via !== undefined ? { via: origin.provenance.via } : {}),
|
|
175
|
+
verification: out && inn ? 'mutual' : out ? 'outgoing' : inn ? 'incoming' : 'met',
|
|
176
|
+
trust: {
|
|
177
|
+
given: trusted,
|
|
178
|
+
received: tuples.some((t) => t.mappingIn.body !== null),
|
|
179
|
+
paused: c.settings.star === 'off' && c.settings.groupStar === 'off',
|
|
180
|
+
pending,
|
|
181
|
+
},
|
|
182
|
+
classes: { ...classes, sealedGroupStar: { ...classes.sealedGroupStar, groups } },
|
|
183
|
+
...(sharedGroups ? { sharedGroups } : {}),
|
|
184
|
+
...(profile ? { profile } : {}),
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
const itemView = (digest, it) => {
|
|
188
|
+
const status = triasOf(it);
|
|
189
|
+
const last = it.history[it.history.length - 1];
|
|
190
|
+
let decisive;
|
|
191
|
+
for (let i = it.history.length - 1; i >= 0 && !decisive; i--)
|
|
192
|
+
if (it.history[i].status !== 'awaiting-transport')
|
|
193
|
+
decisive = it.history[i];
|
|
194
|
+
const v = {
|
|
195
|
+
digest, type: it.type, threadId: it.threadId, contactId: it.recipient.contactId, status,
|
|
196
|
+
attempt: it.attempt, submittedAt: it.history[0]?.at ?? 0, updatedAt: last?.at ?? 0,
|
|
197
|
+
};
|
|
198
|
+
if (last?.status === 'awaiting-transport')
|
|
199
|
+
v.awaiting = last.reason;
|
|
200
|
+
if (decisive?.status === 'delivered')
|
|
201
|
+
v.late = decisive.late;
|
|
202
|
+
if (decisive?.status === 'failed') {
|
|
203
|
+
v.reason = decisive.reason;
|
|
204
|
+
if (decisive.reason === 'rejected-by-receiver')
|
|
205
|
+
v.code = decisive.code;
|
|
206
|
+
}
|
|
207
|
+
if (it.nextAttemptAt !== undefined)
|
|
208
|
+
v.nextAttemptAt = it.nextAttemptAt;
|
|
209
|
+
return v;
|
|
210
|
+
};
|
|
211
|
+
// ── the views ──────────────────────────────────────────────────────────
|
|
212
|
+
/** Every contact, in entry-commit order (2120), then by id. */
|
|
213
|
+
export function contactsView(state) {
|
|
214
|
+
const order = Object.values(state.contacts).sort((a, b) => {
|
|
215
|
+
if (a.pos !== null && b.pos !== null)
|
|
216
|
+
return cmpDec(a.pos, b.pos) || cmp(a.id, b.id);
|
|
217
|
+
if (a.pos !== null)
|
|
218
|
+
return -1;
|
|
219
|
+
if (b.pos !== null)
|
|
220
|
+
return 1;
|
|
221
|
+
return cmp(a.id, b.id);
|
|
222
|
+
});
|
|
223
|
+
const ix = entryIndex(state);
|
|
224
|
+
const rix = recordIndex(state);
|
|
225
|
+
return freezeDeep(order.map((c) => project(state, c, ix, rix)));
|
|
226
|
+
}
|
|
227
|
+
/** One contact by entry id or alias; undefined if there is none. */
|
|
228
|
+
export function contactView(state, id) {
|
|
229
|
+
const c = findContact(state, id);
|
|
230
|
+
return c ? freezeDeep(project(state, c, entryIndex(state), recordIndex(state))) : undefined;
|
|
231
|
+
}
|
|
232
|
+
/** The holder's groups, by genesis digest. */
|
|
233
|
+
export function groupsView(state) {
|
|
234
|
+
return freezeDeep(Object.values(state.groups).sort((a, b) => cmp(a.id, b.id)).map((g) => ({
|
|
235
|
+
commitSeq: state.commitSeq, id: g.id, name: g.name, listed: g.listed, vouchThreshold: g.rules.vouchThreshold,
|
|
236
|
+
members: Object.values(g.roster).sort((a, b) => cmp(a.anchor, b.anchor)).map((m) => ({
|
|
237
|
+
anchor: m.anchor, ...(m.name !== undefined ? { name: m.name } : {}), ...(m.contactId !== undefined ? { contactId: m.contactId } : {}), self: m.anchor === g.memberAnchor,
|
|
238
|
+
})),
|
|
239
|
+
pending: Object.values(g.evidence).map((e) => {
|
|
240
|
+
const acc = e.accept.payload?.accept;
|
|
241
|
+
return { member: acc?.subject ?? '', ...(typeof acc?.card?.name === 'string' ? { name: acc.card.name } : {}), vouches: e.vouches.length };
|
|
242
|
+
}).sort((a, b) => cmp(a.member, b.member)),
|
|
243
|
+
})));
|
|
244
|
+
}
|
|
245
|
+
/** The holder's own profile. */
|
|
246
|
+
export function profileView(state) {
|
|
247
|
+
return freezeDeep({ commitSeq: state.commitSeq, revision: state.profile.revision, ...profileFields(state.profile.body) });
|
|
248
|
+
}
|
|
249
|
+
/** The open prompts, by opening time, then id. Expired prompts stay
|
|
250
|
+
* listed until tick removes them; deciding one is refused. */
|
|
251
|
+
export function promptsView(state) {
|
|
252
|
+
return freezeDeep(Object.values(state.prompts).sort((a, b) => (a.openedAt - b.openedAt) || cmp(a.id, b.id)).map((p) => ({
|
|
253
|
+
commitSeq: state.commitSeq, id: p.id, kind: p.kind,
|
|
254
|
+
...(p.contactId !== undefined ? { contactId: p.contactId } : {}),
|
|
255
|
+
...(p.groupId !== undefined ? { groupId: p.groupId } : {}),
|
|
256
|
+
openedAt: p.openedAt,
|
|
257
|
+
...(p.expiresAt !== undefined ? { expiresAt: p.expiresAt } : {}),
|
|
258
|
+
})));
|
|
259
|
+
}
|
|
260
|
+
/** The sender status of the documents whose digest or threadId is `x`. */
|
|
261
|
+
export function deliveryStatusView(state, x) {
|
|
262
|
+
const items = Object.entries(state.outbox)
|
|
263
|
+
.filter(([digest, it]) => digest === x || it.threadId === x)
|
|
264
|
+
.map(([digest, it]) => itemView(digest, it))
|
|
265
|
+
.sort((a, b) => (a.submittedAt - b.submittedAt) || cmp(a.digest, b.digest));
|
|
266
|
+
return freezeDeep({ commitSeq: state.commitSeq, items });
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=views.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"views.js","sourceRoot":"","sources":["../src/views.ts"],"names":[],"mappings":"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","sourcesContent":["// views — what an app reads: pure projections of the holder's state\n// (lib Stage 2, note §4.5).\n//\n// `state → View`, synchronous, without the engine: every function here\n// reads one state and returns fresh, deep-frozen objects that share no\n// reference with it, so a UI can keep them and the state stays untouched.\n// Each view carries the commitSeq of the state it was read from; views of\n// one snapshot belong together. The holder hands them out over its\n// snapshot (holder-api.ts); after a `subscribe` announcement the app\n// re-reads them. Views never write: whatever ages state (expiry, the\n// encounter's aging latch) is an act, never a read.\n//\n// Rule numbers: bare four-digit numbers are RLTP-TRU (trust-layer.md).\n//\n// Choices this file makes where the note leaves them open:\n// - contacts are listed in entry-commit order (2120); entries without a\n// position (2060) follow, by id. A contact is found by its entry id or\n// by any of its aliases (2140)\n// - provenance and via come from the contact's oldest relationship (by\n// its provenance time, then id): how the person came, not how often\n// - tuples belong to the entry their entryId names (2145): an entry's\n// tuples are those whose entryId is its id or one of its aliases, over\n// its own relationships and any relationship that stands behind two\n// entries. Its heads are the active-head tuples among them of live\n// relationships (not chained into another), not deactivated; under\n// 2146 the appended tuple's entry takes the chain's active head\n// - verification is the edge of Encounter 4.2 over all of the entry's\n// tuples, deactivated and older ones included (historical evidence;\n// one edge per relationship, carried along its chain): `outgoing` an\n// own step credential was issued, `incoming` the counterparty's was\n// accepted (5.6), `mutual` both, `met` neither — read from the\n// enactment records of those tuples (encounter/ceremony.ts). An entry\n// with no record at all (built without a ceremony: introduced, or a\n// test state) reads the anchor mappings instead: `outgoing` one was\n// issued (mappingOut), `incoming` one was verified (mappingIn)\n// - displayName: the profile's name (6425), else the self-declared name\n// on the counterparty card of the entry's newest record (Encounter\n// 6120: the app binds its own local name to the anchor)\n// - trust.given is the anchor mapping class on (the Trust act, 2770);\n// trust.received a verified anchor mapping from the contact, whose\n// class has no default recipient (2760); trust.paused the pause of 5.4,\n// star and blinded group star both `off` (2780); trust.pending: given,\n// but not yet out on every head (no mapping issued on it, or its\n// relationship lags (6595)), or a re-issue or class-on duty for the\n// anchor mapping is open at a version this library handles (a duty of\n// an unhandled version is opaque, note §2.1). Delivery of the documents is not part of\n// it; deliveryStatus answers that\n// - classes give the setting and whether the class is on toward the\n// contact (2760, 2840); the sealed group star also per group (2830):\n// every group of the holder and every group the contact holds a\n// per-group setting for, by id, with the setting (`default` where none\n// is held) and whether it is on for (group, contact) — the per-group\n// setting first, else the class (trust/group-star.ts sealedOn)\n// - sharedGroups: the union of the groups the last accepted group star\n// on each of the entry's heads hit (5520, trust/group-star.ts), lagging\n// heads included (the group star travels on them, 6595); undefined\n// where no head ever accepted one\n// - a contact's profile (6425): among the verified profile@1 bodies\n// (6b.2) on its heads whose relationship does not lag (6461, 6595),\n// the highest revision, among equal ones the one verified last\n// (highest verifiedSeq); displayName is that profile's name\n// - deliveryStatus(x) lists the outbox items whose digest or threadId is\n// x, by first submission, then digest; an unknown x lists none\n// - relationships: the entry's own (relIds), in that order; chainedFrom\n// the husks chained into each (chainedInto), by id\n// - a contact without a relationship breaks an invariant and throws\nimport { freezeDeep } from './util-freeze.js'\nimport type { Json } from './core.js'\nimport { triasOf } from './state.js'\nimport { CLASSES, activeTuple, classOn, findContact, lags, trusted as isTrusted } from './trust/state.js'\nimport { sealedOn } from './trust/group-star.js'\nimport { classOfDuty } from './trust/duties.js'\nimport type {\n EnactmentRecord,\n Contact, Dec, HolderState, Millis, OutboxItem, OutboxStatus, PromptKind, Relationship, Setting, TrustClass, Tuple,\n} from './state.js'\nimport type { DeliveryFailure, PreTransportReason, ReceiverRefusalCode } from './ports.js'\n\n/** One trust class toward one contact: its setting (2810) and whether it is on (2760). */\nexport interface ClassView { setting: Setting, on: boolean }\n\n/** The sealed group star toward one contact: the class, and per group\n * (2830) the per-group setting and whether it is on for (group, contact). */\nexport interface SealedClassView extends ClassView { groups: Record<string, ClassView> }\n\n/** Every class toward one contact (2720), the sealed group star per group too. */\nexport type ClassesView = Record<Exclude<TrustClass, 'sealedGroupStar'>, ClassView> & { sealedGroupStar: SealedClassView }\n\n/** A contact's verified profile (6b.2): string fields only. */\nexport interface ContactProfileView { revision: Dec, name?: string, image?: string, text?: string }\n\n/** One contact, i.e. one entry of the deliverable set (2120, 2140). */\nexport interface ContactView {\n /** the commitSeq of the state this view was read from */\n commitSeq: Dec\n /** the entry id: stable across aliases (2140) and chains (6a.4) */\n id: string\n /** identities merged into this entry (2140) and the fresh contacts its\n * chains took in (6a.4); contact(alias) finds it too */\n aliases: string[]\n /** its relationships (Contact.relIds), each with the number of tuples\n * its chain holds (one per enactment that continued it, 6.4) and the\n * fresh relationships chained into it (6a.4); a relationship that\n * stands behind two entries (2145) is listed under both */\n relationships: RelationshipView[]\n /** the verified profile's name (6425); the ceremony card's name enters\n * the state only when Encounter graduates (PR 7), so without a profile\n * it is undefined */\n displayName?: string\n provenance: 'ceremony' | 'introduced'\n /** the introducer, for an introduced contact */\n via?: string\n verification: 'mutual' | 'outgoing' | 'incoming' | 'met'\n trust: { given: boolean, received: boolean, paused: boolean, pending: boolean }\n classes: ClassesView\n /** groups shared with the contact: the groups of the holder whose\n * digest hit in the contact's last completed group star (5520), over\n * its heads, sorted. A hit is the contact's claim (5.2, no veracity).\n * Undefined while no group star was ever accepted on a head, never a\n * claimed empty list. */\n sharedGroups?: string[]\n profile?: ContactProfileView\n}\n\n/** One relationship of a contact, as its chain stands. */\nexport interface RelationshipView { id: string, tuples: number, chainedFrom: string[] }\n\n/** One group the holder is a member of. */\nexport interface GroupView {\n commitSeq: Dec\n /** genesis digest */\n id: string\n /** the group's name, as its genesis names it */\n name: string\n /** listed in the blinded group star (5.2b per-group switch) */\n listed: boolean\n vouchThreshold: Dec\n /** the members this holder knows of, by member anchor (its roster);\n * `self` marks the own one, `contactId` a member it knows as a contact */\n members: Array<{ anchor: string, name?: string, contactId?: string, self: boolean }>\n /** consent pairs held toward an admission (Membership 3.4), by subject */\n pending: Array<{ member: string, name?: string, vouches: number }>\n}\n\n/** The holder's own profile (6450). */\nexport interface ProfileView { commitSeq: Dec, revision: Dec, name?: string, image?: string, text?: string }\n\n/** One open decision of the human. */\nexport interface PromptView {\n commitSeq: Dec\n id: string\n kind: PromptKind\n contactId?: string\n groupId?: string\n openedAt: Millis\n expiresAt?: Millis\n}\n\n/** One issued document's sender status (Delivery §6.1). */\nexport interface DeliveryItemView {\n digest: string\n type: string\n threadId: string\n contactId: string\n /** the trias position */\n status: OutboxStatus\n /** the adapter holds the item before the trias (last step awaiting-transport) */\n awaiting?: PreTransportReason\n /** for delivered: after a failure (the holder's own give-up included) */\n late?: boolean\n /** for failed */\n reason?: DeliveryFailure\n code?: ReceiverRefusalCode\n attempt: number\n submittedAt: Millis\n updatedAt: Millis\n nextAttemptAt?: Millis\n}\n\nexport interface DeliveryStatusView { commitSeq: Dec, items: DeliveryItemView[] }\n\n// ── helpers ────────────────────────────────────────────────────────────\n\nconst cmp = (a: string, b: string): number => (a < b ? -1 : a > b ? 1 : 0)\nconst cmpDec = (a: Dec, b: Dec): number => { const x = BigInt(a), y = BigInt(b); return x < y ? -1 : x > y ? 1 : 0 }\nconst isObj = (x: unknown): x is Record<string, Json> => x !== null && typeof x === 'object' && !Array.isArray(x)\n\n/** The string fields of a profile body that a view shows. */\nconst profileFields = (body: Json | null): { name?: string, image?: string, text?: string } => {\n const out: { name?: string, image?: string, text?: string } = {}\n if (!isObj(body)) return out\n for (const k of ['name', 'image', 'text'] as const) if (typeof body[k] === 'string') out[k] = body[k] as string\n return out\n}\n\n/** own pair label → its enactment record (encounter.records) */\ntype RecordIndex = Map<string, EnactmentRecord>\n\nconst recordIndex = (state: Readonly<HolderState>): RecordIndex => {\n const ix: RecordIndex = new Map()\n for (const r of Object.values(state.encounter.records)) ix.set(r.label, r)\n return ix\n}\n\n/** entry id → the relationships holding a tuple of that entry (2145) */\ntype EntryIndex = Map<string, Set<string>>\n\nconst entryIndex = (state: Readonly<HolderState>): EntryIndex => {\n const ix: EntryIndex = new Map()\n for (const r of Object.values(state.relationships)) {\n for (const t of r.tuples) {\n let s = ix.get(t.entryId)\n if (!s) ix.set(t.entryId, (s = new Set()))\n s.add(r.id)\n }\n }\n return ix\n}\n\n/** The contact's own relationships, then those holding a tuple of its entry. */\nconst relationshipsOf = (state: Readonly<HolderState>, c: Readonly<Contact>, ids: ReadonlySet<string>, ix: EntryIndex): { own: Relationship[], all: Relationship[] } => {\n const own = c.relIds.filter((id) => Object.hasOwn(state.relationships, id)).map((id) => state.relationships[id])\n if (!own.length) throw new Error(`views: contact ${c.id} has no relationship`)\n const seen = new Set(own.map((r) => r.id))\n const all = [...own]\n for (const id of ids) {\n for (const rid of ix.get(id) ?? []) {\n if (!seen.has(rid)) { seen.add(rid); all.push(state.relationships[rid]) }\n }\n }\n return { own, all }\n}\n\nconst project = (state: Readonly<HolderState>, c: Readonly<Contact>, ix: EntryIndex, rix: RecordIndex): ContactView => {\n const ids = new Set([c.id, ...c.aliases])\n const { own, all: rels } = relationshipsOf(state, c, ids, ix)\n const mine = (t: Tuple): boolean => ids.has(t.entryId)\n const tuples = rels.flatMap((r) => r.tuples.filter(mine))\n const origin = [...own].sort((a, b) => (a.provenance.at - b.provenance.at) || cmp(a.id, b.id))[0]\n const records = tuples.map((t) => rix.get(t.ownPairLabel)).filter((r): r is EnactmentRecord => r !== undefined)\n const out = records.length ? records.some((r) => r.out !== null) : tuples.some((t) => t.mappingOut.body !== null)\n const inn = records.length ? records.some((r) => r.in !== null) : tuples.some((t) => t.mappingIn.body !== null)\n const newest = [...records].sort((a, b) => b.at - a.at)[0]\n const introduced = own.map((r) => r.memory.introducedName).find((n): n is string => typeof n === 'string')\n const cardName = typeof (newest?.card as { name?: unknown } | undefined)?.name === 'string' ? (newest.card as { name: string }).name : introduced\n const trusted = isTrusted(c)\n const classes = {} as Record<TrustClass, ClassView>\n for (const cls of CLASSES) classes[cls] = { setting: c.settings[cls], on: classOn(cls, c.settings[cls], trusted) }\n const groups: Record<string, ClassView> = {}\n for (const g of [...new Set([...Object.keys(state.groups), ...Object.keys(c.groupSettings)])].sort(cmp)) {\n groups[g] = { setting: Object.hasOwn(c.groupSettings, g) ? c.groupSettings[g] : 'default', on: sealedOn(c, g) }\n }\n const heads: Array<{ r: Relationship, t: Tuple, lagging: boolean }> = []\n for (const r of rels) {\n if (r.chainedInto !== null) continue\n const t = activeTuple(r)\n if (t && !t.deactivated && mine(t)) heads.push({ r, t, lagging: lags(r, rels) })\n }\n // a class-on or re-issue of the anchor mapping, at a version this library\n // handles (classOfDuty: an unhandled version is opaque and owes nothing here)\n const owed = Object.values(state.duties).some((d) =>\n classOfDuty(d) === 'anchorMapping' && (d as { contactId?: unknown }).contactId === c.id)\n const pending = trusted && (owed || heads.some((h) => h.t.mappingOut.body === null || h.lagging))\n let best: Tuple | undefined\n for (const { t, lagging } of heads) {\n if (lagging || t.profileIn.body === null) continue\n if (!best || cmpDec(t.profileIn.rev, best.profileIn.rev) > 0 ||\n (cmpDec(t.profileIn.rev, best.profileIn.rev) === 0 && cmpDec(t.profileIn.verifiedSeq, best.profileIn.verifiedSeq) > 0)) best = t\n }\n const profile = best ? { revision: best.profileIn.rev, ...profileFields(best.profileIn.body) } : undefined\n const received = heads.map((h) => h.t.groupStarIn.accepted).filter((a) => a !== null)\n const sharedGroups = received.length ? [...new Set(received.flatMap((a) => a.groups))].sort(cmp) : undefined\n return {\n commitSeq: state.commitSeq,\n id: c.id,\n aliases: [...c.aliases],\n relationships: own.map((r) => ({\n id: r.id, tuples: r.tuples.length,\n chainedFrom: Object.values(state.relationships).filter((x) => x.chainedInto === r.id).map((x) => x.id).sort(cmp),\n })),\n ...(profile?.name !== undefined ? { displayName: profile.name } : cardName !== undefined ? { displayName: cardName } : {}),\n provenance: origin.provenance.kind,\n ...(origin.provenance.kind === 'introduced' && origin.provenance.via !== undefined ? { via: origin.provenance.via } : {}),\n verification: out && inn ? 'mutual' : out ? 'outgoing' : inn ? 'incoming' : 'met',\n trust: {\n given: trusted,\n received: tuples.some((t) => t.mappingIn.body !== null),\n paused: c.settings.star === 'off' && c.settings.groupStar === 'off',\n pending,\n },\n classes: { ...classes, sealedGroupStar: { ...classes.sealedGroupStar, groups } } as ClassesView,\n ...(sharedGroups ? { sharedGroups } : {}),\n ...(profile ? { profile } : {}),\n }\n}\n\nconst itemView = (digest: string, it: Readonly<OutboxItem>): DeliveryItemView => {\n const status = triasOf(it)\n const last = it.history[it.history.length - 1]\n let decisive: OutboxItem['history'][number] | undefined\n for (let i = it.history.length - 1; i >= 0 && !decisive; i--) if (it.history[i].status !== 'awaiting-transport') decisive = it.history[i]\n const v: DeliveryItemView = {\n digest, type: it.type, threadId: it.threadId, contactId: it.recipient.contactId, status,\n attempt: it.attempt, submittedAt: it.history[0]?.at ?? 0, updatedAt: last?.at ?? 0,\n }\n if (last?.status === 'awaiting-transport') v.awaiting = last.reason\n if (decisive?.status === 'delivered') v.late = decisive.late\n if (decisive?.status === 'failed') {\n v.reason = decisive.reason\n if (decisive.reason === 'rejected-by-receiver') v.code = decisive.code\n }\n if (it.nextAttemptAt !== undefined) v.nextAttemptAt = it.nextAttemptAt\n return v\n}\n\n// ── the views ──────────────────────────────────────────────────────────\n\n/** Every contact, in entry-commit order (2120), then by id. */\nexport function contactsView (state: Readonly<HolderState>): ContactView[] {\n const order = Object.values(state.contacts).sort((a, b) => {\n if (a.pos !== null && b.pos !== null) return cmpDec(a.pos, b.pos) || cmp(a.id, b.id)\n if (a.pos !== null) return -1\n if (b.pos !== null) return 1\n return cmp(a.id, b.id)\n })\n const ix = entryIndex(state)\n const rix = recordIndex(state)\n return freezeDeep(order.map((c) => project(state, c, ix, rix)))\n}\n\n/** One contact by entry id or alias; undefined if there is none. */\nexport function contactView (state: Readonly<HolderState>, id: string): ContactView | undefined {\n const c = findContact(state, id)\n return c ? freezeDeep(project(state, c, entryIndex(state), recordIndex(state))) : undefined\n}\n\n/** The holder's groups, by genesis digest. */\nexport function groupsView (state: Readonly<HolderState>): GroupView[] {\n return freezeDeep(Object.values(state.groups).sort((a, b) => cmp(a.id, b.id)).map((g) => ({\n commitSeq: state.commitSeq, id: g.id, name: g.name, listed: g.listed, vouchThreshold: g.rules.vouchThreshold,\n members: Object.values(g.roster).sort((a, b) => cmp(a.anchor, b.anchor)).map((m) => ({\n anchor: m.anchor, ...(m.name !== undefined ? { name: m.name } : {}), ...(m.contactId !== undefined ? { contactId: m.contactId } : {}), self: m.anchor === g.memberAnchor,\n })),\n pending: Object.values(g.evidence).map((e) => {\n const acc = (e.accept as { payload?: { accept?: { subject?: string, card?: { name?: string } } } }).payload?.accept\n return { member: acc?.subject ?? '', ...(typeof acc?.card?.name === 'string' ? { name: acc.card.name } : {}), vouches: e.vouches.length }\n }).sort((a, b) => cmp(a.member, b.member)),\n })))\n}\n\n/** The holder's own profile. */\nexport function profileView (state: Readonly<HolderState>): ProfileView {\n return freezeDeep({ commitSeq: state.commitSeq, revision: state.profile.revision, ...profileFields(state.profile.body) })\n}\n\n/** The open prompts, by opening time, then id. Expired prompts stay\n * listed until tick removes them; deciding one is refused. */\nexport function promptsView (state: Readonly<HolderState>): PromptView[] {\n return freezeDeep(Object.values(state.prompts).sort((a, b) => (a.openedAt - b.openedAt) || cmp(a.id, b.id)).map((p) => ({\n commitSeq: state.commitSeq, id: p.id, kind: p.kind,\n ...(p.contactId !== undefined ? { contactId: p.contactId } : {}),\n ...(p.groupId !== undefined ? { groupId: p.groupId } : {}),\n openedAt: p.openedAt,\n ...(p.expiresAt !== undefined ? { expiresAt: p.expiresAt } : {}),\n })))\n}\n\n/** The sender status of the documents whose digest or threadId is `x`. */\nexport function deliveryStatusView (state: Readonly<HolderState>, x: string): DeliveryStatusView {\n const items = Object.entries(state.outbox)\n .filter(([digest, it]) => digest === x || it.threadId === x)\n .map(([digest, it]) => itemView(digest, it))\n .sort((a, b) => (a.submittedAt - b.submittedAt) || cmp(a.digest, b.digest))\n return freezeDeep({ commitSeq: state.commitSeq, items })\n}\n"]}
|
package/dist/visibility.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export *
|
|
4
|
-
export *
|
|
5
|
-
export *
|
|
1
|
+
export * from './anchor.js';
|
|
2
|
+
export * from './star.js';
|
|
3
|
+
export * from './group-star.js';
|
|
4
|
+
export * from './continuity.js';
|
|
5
|
+
export * from './ack.js';
|
|
6
6
|
//# sourceMappingURL=visibility.d.ts.map
|
package/dist/visibility.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../src/visibility.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../src/visibility.ts"],"names":[],"mappings":"AAmBA,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,UAAU,CAAA"}
|
package/dist/visibility.js
CHANGED
|
@@ -1,31 +1,25 @@
|
|
|
1
|
-
// @real-life/trust-protocol — visibility: the
|
|
2
|
-
//
|
|
1
|
+
// @real-life/trust-protocol — visibility: the Trust Layer's wire forms
|
|
2
|
+
// (Trust Layer 0.31 with Identity 0.54 §5.4, on Delivery 0.81), pure
|
|
3
|
+
// builders and verifiers, no state. Byte-compatible with
|
|
4
|
+
// vectors/visibility.json, vectors/anchor-rotation.json,
|
|
5
|
+
// vectors/group-star.json and vectors/delivery-ack.json.
|
|
3
6
|
//
|
|
4
|
-
//
|
|
5
|
-
// (
|
|
6
|
-
//
|
|
7
|
-
//
|
|
7
|
+
// anchor self-card@2, anchor-rotation@2 with the pre-rotation
|
|
8
|
+
// binding, the lineage (§6.5), anchor-mapping@4 (§6.1/§6.3,
|
|
9
|
+
// conditions 4a and 4b, condition 8 for a changed self)
|
|
10
|
+
// star star@2 chunks (5.2, 5.2a): the key, blinding, chunking
|
|
11
|
+
// group-star group-star@1 (§5.2b): keys, the sealed group-pair@1,
|
|
12
|
+
// build, assemble, open; entropy from the caller
|
|
13
|
+
// continuity §6a: continuity-probe@1 chunks, continuity-mapping@1
|
|
14
|
+
// (both MACs), the record side
|
|
15
|
+
// ack delivery-ack/0.1 in both classes (Delivery 4.2): the
|
|
16
|
+
// channel ack key, the MAC form, the signed form
|
|
8
17
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
// acks the deniable delivery-ack/0.1 under the channel ack
|
|
17
|
-
// key (Delivery 4.2 class rule)
|
|
18
|
-
//
|
|
19
|
-
// Wire forms and keys are byte-compatible with vectors/visibility.json
|
|
20
|
-
// and vectors/delivery-ack.json. The modules operate on the probe WORLD
|
|
21
|
-
// (a `Person` holding contexts, contacts, groups — DOM-free and storage-
|
|
22
|
-
// free); the host decides where bytes live.
|
|
23
|
-
//
|
|
24
|
-
// Not in this module: transport adapters and their policies, storage,
|
|
25
|
-
// the Encounter layer's ceremony flows (graduated separately as
|
|
26
|
-
// `ceremony` on 05.09.2026).
|
|
27
|
-
export { COMMUNITY_GENESIS } from './probe/deps.js';
|
|
28
|
-
export * as trust from './probe/trust.js';
|
|
29
|
-
export * as continuity from './probe/continuity.js';
|
|
30
|
-
export * as acks from './probe/acks.js';
|
|
18
|
+
// The stateful acts (the trust act, the reconciled star, the admission
|
|
19
|
+
// layer, the chaining) are the holder's (createHolder).
|
|
20
|
+
export * from './anchor.js';
|
|
21
|
+
export * from './star.js';
|
|
22
|
+
export * from './group-star.js';
|
|
23
|
+
export * from './continuity.js';
|
|
24
|
+
export * from './ack.js';
|
|
31
25
|
//# sourceMappingURL=visibility.js.map
|
package/dist/visibility.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visibility.js","sourceRoot":"","sources":["../src/visibility.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"visibility.js","sourceRoot":"","sources":["../src/visibility.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,qEAAqE;AACrE,yDAAyD;AACzD,yDAAyD;AACzD,yDAAyD;AACzD,EAAE;AACF,sEAAsE;AACtE,2EAA2E;AAC3E,uEAAuE;AACvE,wEAAwE;AACxE,sEAAsE;AACtE,gEAAgE;AAChE,sEAAsE;AACtE,8CAA8C;AAC9C,sEAAsE;AACtE,gEAAgE;AAChE,EAAE;AACF,uEAAuE;AACvE,wDAAwD;AACxD,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,UAAU,CAAA","sourcesContent":["// @real-life/trust-protocol — visibility: the Trust Layer's wire forms\n// (Trust Layer 0.31 with Identity 0.54 §5.4, on Delivery 0.81), pure\n// builders and verifiers, no state. Byte-compatible with\n// vectors/visibility.json, vectors/anchor-rotation.json,\n// vectors/group-star.json and vectors/delivery-ack.json.\n//\n// anchor self-card@2, anchor-rotation@2 with the pre-rotation\n// binding, the lineage (§6.5), anchor-mapping@4 (§6.1/§6.3,\n// conditions 4a and 4b, condition 8 for a changed self)\n// star star@2 chunks (5.2, 5.2a): the key, blinding, chunking\n// group-star group-star@1 (§5.2b): keys, the sealed group-pair@1,\n// build, assemble, open; entropy from the caller\n// continuity §6a: continuity-probe@1 chunks, continuity-mapping@1\n// (both MACs), the record side\n// ack delivery-ack/0.1 in both classes (Delivery 4.2): the\n// channel ack key, the MAC form, the signed form\n//\n// The stateful acts (the trust act, the reconciled star, the admission\n// layer, the chaining) are the holder's (createHolder).\nexport * from './anchor.js'\nexport * from './star.js'\nexport * from './group-star.js'\nexport * from './continuity.js'\nexport * from './ack.js'\n"]}
|