@real-life/trust-protocol 0.3.2 → 0.5.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 +97 -0
- package/README.md +209 -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 +169 -0
- package/dist/adapters/vti-mediator.d.ts.map +1 -0
- package/dist/adapters/vti-mediator.js +659 -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 +54 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +494 -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 +303 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +1509 -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 +198 -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 +165 -0
- package/dist/holder-api.d.ts.map +1 -0
- package/dist/holder-api.js +142 -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/holder-state-v2.d.ts +858 -0
- package/dist/holder-state-v2.d.ts.map +1 -0
- package/dist/holder-state-v2.js +2 -0
- package/dist/holder-state-v2.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 +27 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +81 -29
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +37 -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 +764 -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 +953 -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 +33 -0
- package/dist/membership/holder.d.ts.map +1 -0
- package/dist/membership/holder.js +929 -0
- package/dist/membership/holder.js.map +1 -0
- package/dist/membership.d.ts +123 -0
- package/dist/membership.d.ts.map +1 -0
- package/dist/membership.js +180 -0
- package/dist/membership.js.map +1 -0
- package/dist/message/holder.d.ts +49 -0
- package/dist/message/holder.d.ts.map +1 -0
- package/dist/message/holder.js +290 -0
- package/dist/message/holder.js.map +1 -0
- package/dist/message.d.ts +43 -0
- package/dist/message.d.ts.map +1 -0
- package/dist/message.js +51 -0
- package/dist/message.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 +134 -0
- package/dist/receive.d.ts.map +1 -0
- package/dist/receive.js +317 -0
- package/dist/receive.js.map +1 -0
- package/dist/results.d.ts +173 -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 +45 -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 +914 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +37 -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 +1222 -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 +795 -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 +179 -0
- package/dist/views.d.ts.map +1 -0
- package/dist/views.js +286 -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 +218 -83
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js.map +1 -1
- package/package.json +60 -10
- package/schemas/holder-state-v1.schema.json +3880 -0
- package/schemas/holder-state-v2.schema.json +4123 -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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"membership.js","sourceRoot":"","sources":["../src/membership.ts"],"names":[],"mappings":"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","sourcesContent":["// membership — the pure forms and checks of Membership Tasks 0.20 (the\n// prelude, the invite, the accept, the evidence relay) and of the vouch@2 credential\n// (Access 0.57 5.3), used by the holder's membership module\n// (membership/holder.ts). State-free: which invitation a holder sent,\n// which group it is in, are the module's.\nimport { b64uOf, calOK, fromB64u, jcs, makeValidator, sameDigest, toU, tsec } from './core.js'\nimport { diVerify } from './crypto.js'\nimport { SCHEMAS } from './schemas.js'\n\nconst TT = 'https://real-life.org/trust-tasks/'\nexport const INVITE_TYPE = TT + 'membership-invite/0.2'\nexport const ACCEPT_TYPE = TT + 'membership-accept/0.2'\nexport const EVIDENCE_TYPE = TT + 'membership-evidence/0.2'\n/** accepted under the same rules, never issued (RLTP-MT-3815) */\nexport const EVIDENCE_TYPE_01 = TT + 'membership-evidence/0.1'\n/** The prelude (Membership 3.5): the inviter's request and the invitee's reply. */\nexport const PRELUDE_REQUEST_TYPE = TT + 'membership-prelude-request/0.1'\nexport const PRELUDE_REPLY_TYPE = TT + 'membership-prelude-reply/0.1'\n/** The inviter binding's artifact type (RLTP-MT-3905). */\nexport const INVITER_BINDING_TYPE = 'membership-inviter@1'\n\n/** membership-skew, PT5M (Membership §5, RLTP-MT-5050), in ms. */\nexport const MEMBERSHIP_SKEW = 300_000\n/** The membership size budget: JCS bytes of an invite or accept document (2.5). */\nexport const MEMBERSHIP_BUDGET = 16_384\n/** The pinned credential contexts of the invite and the vouch (RLTP-MT-3015). */\nexport const MEMBERSHIP_CONTEXT: readonly string[] = Object.freeze([\n 'https://www.w3.org/ns/credentials/v2', 'https://firstperson.network/credentials/dtg/v1', 'https://real-life.org/rltp/v1',\n])\n\nconst V = makeValidator(SCHEMAS)\nexport const membershipSchemaOk = (file: string, data: unknown): boolean => V.validate(data, SCHEMAS[file], SCHEMAS[file]).length === 0\nconst te = new TextEncoder()\n/** Within the membership size budget (2.5, RLTP-MT-2200)? */\nexport const withinBudget = (doc: unknown): boolean => te.encode(jcs(doc)).length <= MEMBERSHIP_BUDGET\n\n/** The `oid:` form of a sha2-256 multihash digest (Access 3.3, RLTP-ACC-\n * 3100): the same SHA-256, unpadded base64url — the genesis digest and\n * its operation id name one operation. null for anything else. */\nexport const oidOf = (digest: unknown): string | null => {\n const u = toU(digest)\n if (u === null) return null\n const mh = fromB64u(u.slice(1))\n return mh.length === 34 && mh[0] === 0x12 && mh[1] === 0x20 ? 'oid:' + b64uOf(mh.subarray(2)) : null\n}\n\n/** The member context label for a group, from its genesis digest:\n * canonical-u re-encoding before the label (Access 5.1, RLTP-MT-3030);\n * null for a digest that does not decode. */\nexport const memberLabelOf = (genesisDigest: unknown): string | null => {\n const u = toU(genesisDigest)\n return u === null ? null : 'group/' + u\n}\n\n/** An enclosed card's profile (Membership 2.6): the displayed form, its\n * proof under its anchor, no sentTo, boundTo or deliveryHints. */\nexport async function enclosedCardOk (card: any, anchor: string, subtle?: SubtleCrypto): Promise<boolean> {\n if (!membershipSchemaOk('contact-card.schema.json', card)) return false\n if (card.anchor !== anchor) return false\n if ('sentTo' in card || 'boundTo' in card || 'deliveryHints' in card) return false\n return diVerify(card, anchor, subtle)\n}\n\n/** The unsigned InvitationCredential (Membership 3.1, RLTP-MT-3010–3070). */\nexport const inviteCredentialBody = (f: {\n issuer: string, invitee: string, group: string, genesisDigest: string, card: unknown, name?: string,\n validFrom: string, validUntil: string, taskContext: string,\n}) => ({\n '@context': [...MEMBERSHIP_CONTEXT],\n type: ['VerifiableCredential', 'DTGCredential', 'InvitationCredential', 'MembershipInvite'],\n issuer: f.issuer,\n credentialSubject: { id: f.invitee, group: f.group, genesisDigest: f.genesisDigest, card: f.card, ...(f.name !== undefined ? { name: f.name } : {}) },\n validFrom: f.validFrom, validUntil: f.validUntil, taskContext: f.taskContext,\n})\n\n/** The invite document's checks at its recipient (Membership 3.1, 2.4,\n * 2.5), past its payload schema: the credential's proof under its\n * issuer, the document bindings, the card's ownership and profile, the\n * validity dates, no enactment, the budget. The prelude check (3030)\n * needs the recipient's own derivation and stays the caller's. null when\n * they pass, else the rule. */\nexport async function inviteProblem (doc: any, subtle?: SubtleCrypto): Promise<string | null> {\n const inv = doc.payload.invite\n if (!withinBudget(doc)) return 'RLTP-MT-2210'\n if (doc.ceremony?.enactment !== undefined) return 'RLTP-MT-2170'\n if (inv.issuer !== doc.issuer) return 'RLTP-MT-3020'\n if (inv.credentialSubject.id !== doc.recipient) return 'RLTP-MT-3025'\n if (inv.taskContext !== doc.threadId) return 'RLTP-MT-3075'\n if (![inv.validFrom, inv.validUntil, inv.proof?.created].every(calOK) || tsec(inv.validUntil) < tsec(inv.validFrom)) return 'RLTP-MT-3055'\n if (!(await diVerify(inv, inv.issuer, subtle))) return 'RLTP-MT-3070'\n if (!(await enclosedCardOk(inv.credentialSubject.card, inv.issuer, subtle))) return 'RLTP-MT-3050'\n return null\n}\n\n/** The accept's checks against the invite it answers (RLTP-MT-3270),\n * past its schema and the document proof's presence: the proof under the\n * issuer, issuer = subject = the invite's subject, ref = the invite's\n * credential digest, the group, the card, the times, the budget. */\nexport async function acceptProblem (doc: any, invite: any, credDigest: string, subtle?: SubtleCrypto): Promise<string | null> {\n const acc = doc.payload.accept\n const inv = invite.payload.invite\n if (!withinBudget(doc)) return 'RLTP-MT-2210'\n if (doc.proof?.verificationMethod?.split('#')[0] !== doc.issuer) return 'RLTP-MT-2140'\n if (acc.subject !== doc.issuer) return 'RLTP-MT-3220'\n if (acc.subject !== inv.credentialSubject.id) return 'RLTP-MT-3225'\n if (!sameDigest(acc.ref, credDigest)) return 'RLTP-MT-3230'\n if (acc.group !== inv.credentialSubject.group) return 'RLTP-MT-3215'\n if (doc.threadId !== invite.threadId || doc.recipient !== inv.issuer) return 'RLTP-MT-3255'\n if (![doc.issuedAt, doc.proof?.created].every(calOK)) return 'RLTP-MT-3270'\n const last = tsec(inv.validUntil) + MEMBERSHIP_SKEW\n if (tsec(doc.issuedAt) > last || tsec(doc.proof.created) > last) return 'RLTP-MT-3270'\n if (!(await diVerify(doc, doc.issuer, subtle))) return 'RLTP-MT-2130'\n if (!(await enclosedCardOk(acc.card, acc.subject, subtle))) return 'RLTP-MT-3240'\n return null\n}\n\n/** The unsigned vouch@2 (Access 5.3): one member for one consented admission. */\nexport const vouchCredentialBody = (f: { issuer: string, subject: string, genesisDigest: string, accept: string, provenance: 'met' | 'introduced', validFrom: string }) => ({\n '@context': [...MEMBERSHIP_CONTEXT],\n type: ['VerifiableCredential', 'DTGCredential', 'EndorsementCredential', 'AdmissionVouch'],\n issuer: f.issuer,\n validFrom: f.validFrom,\n credentialSubject: { id: f.subject, endorsement: { type: 'AdmissionVouch', genesisDigest: toU(f.genesisDigest), accept: toU(f.accept), provenance: f.provenance } },\n})\n\n/** A vouch's checks for one enclosed pair (RLTP-MT-3810): schema, proof\n * under its issuer, subject, accept and genesis bindings. */\nexport async function vouchProblem (vouch: any, acceptSubject: string, acceptDigest: string, genesisDigest: string, subtle?: SubtleCrypto): Promise<string | null> {\n if (!membershipSchemaOk('access-vouch.schema.json', vouch)) return 'RLTP-MT-3810'\n const e = vouch.credentialSubject.endorsement\n if (vouch.credentialSubject.id !== acceptSubject || !sameDigest(e.accept, acceptDigest) || !sameDigest(e.genesisDigest, genesisDigest)) return 'RLTP-MT-3810'\n if (!(await diVerify(vouch, vouch.issuer, subtle))) return 'RLTP-MT-3810'\n return null\n}\n\n/** The evidence pair's checks (RLTP-MT-3725), past the payload schema. */\nexport async function evidenceProblem (invite: any, accept: any, credDigest: string, subtle?: SubtleCrypto): Promise<string | null> {\n const inv = invite.payload.invite\n if (inv.issuer !== invite.issuer || invite.recipient !== inv.credentialSubject.id) return 'RLTP-MT-3725'\n if (invite.threadId !== inv.taskContext || accept.threadId !== invite.threadId) return 'RLTP-MT-3725'\n if (![inv.validFrom, inv.validUntil].every(calOK) || tsec(inv.validUntil) < tsec(inv.validFrom)) return 'RLTP-MT-3725'\n if (!(await diVerify(inv, inv.issuer, subtle))) return 'RLTP-MT-3725'\n if (!(await enclosedCardOk(inv.credentialSubject.card, inv.issuer, subtle))) return 'RLTP-MT-3725'\n return (await acceptProblem(accept, invite, credDigest, subtle)) === null ? null : 'RLTP-MT-3725'\n}\n\n/** The unsigned inviter binding `membership-inviter@1` (RLTP-MT-3905):\n * the inviter's member anchor, the group's genesis digest, and the\n * request document's threadId, issuer (from) and recipient (to). */\nexport const inviterBindingBody = (f: { inviter: string, genesisDigest: string, threadId: string, from: string, to: string }) => ({\n type: INVITER_BINDING_TYPE, inviter: f.inviter, genesisDigest: f.genesisDigest, threadId: f.threadId, from: f.from, to: f.to,\n})\n\n/** Why a prelude request fails its form (Membership 3.5), the vector\n * cases' `fails` names: the payload schema, the document proof under its\n * issuer (RLTP-MT-3900), the binding's fields against the payload and the\n * document, genesis digests compared by their decoded bytes\n * (RLTP-MT-3905), and the binding proof under its `inviter`. The tuple\n * checks of RLTP-MT-3910 (issuer and recipient the arrival tuple's pair\n * anchors) need holder state and stay the caller's. null when it passes. */\nexport type PreludeRequestProblem = 'schema' | 'documentProof' | 'bindingFields' | 'bindingProof'\nexport async function preludeRequestProblem (doc: any, subtle?: SubtleCrypto): Promise<PreludeRequestProblem | null> {\n if (!membershipSchemaOk('payload-membership-prelude-request.schema.json', doc?.payload)) return 'schema'\n if (!(await diVerify(doc, doc.issuer, subtle))) return 'documentProof'\n const p = doc.payload, b = p.binding\n if (b.inviter !== p.inviter || !sameDigest(b.genesisDigest, p.genesisDigest) || b.threadId !== doc.threadId || b.from !== doc.issuer || b.to !== doc.recipient) return 'bindingFields'\n if (!(await diVerify(b, b.inviter, subtle))) return 'bindingProof'\n return null\n}\n"]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { HolderModule, Refusal } from '../engine.js';
|
|
2
|
+
import type { HolderState, Millis, Rates, Relationship, Tuple } from '../state.js';
|
|
3
|
+
export declare const MESSAGE_COMMANDS: Readonly<{
|
|
4
|
+
readonly send: "message.send";
|
|
5
|
+
readonly block: "message.block";
|
|
6
|
+
readonly take: "message.take";
|
|
7
|
+
}>;
|
|
8
|
+
/** The rate window of Message Tasks 4.2: any 24 hours. */
|
|
9
|
+
export declare const RATE_WINDOW = 86400000;
|
|
10
|
+
/** At most 20 invitations with a new credential digest per relationship
|
|
11
|
+
* and window (RLTP-MSG-4115, Membership RLTP-MT-3105). */
|
|
12
|
+
export declare const INVITE_RATE = 20;
|
|
13
|
+
export interface BlockInput {
|
|
14
|
+
contactId: string;
|
|
15
|
+
blocked: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface SendInput {
|
|
18
|
+
contactId: string;
|
|
19
|
+
text: string;
|
|
20
|
+
replyTo?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface TakeInput {
|
|
23
|
+
ids: string[];
|
|
24
|
+
}
|
|
25
|
+
/** Whether the relationship is blocked (RLTP-MSG-6010). */
|
|
26
|
+
export declare const blockedRel: (state: Readonly<HolderState>, relId: string) => boolean;
|
|
27
|
+
/** The relationship id the own tuple key `rkid` belongs to now, or null. */
|
|
28
|
+
export declare const relOfRkid: (state: Readonly<HolderState>, rkid: string) => string | null;
|
|
29
|
+
/** Whether any relationship of the entry `id` names (by id or alias) is blocked. */
|
|
30
|
+
export declare const blockedContact: (state: Readonly<HolderState>, id: string) => boolean;
|
|
31
|
+
/** The blocked set with `relIds` set or cleared, sorted. */
|
|
32
|
+
export declare const withBlocked: (blocked: readonly string[], relIds: readonly string[], on: boolean) => string[];
|
|
33
|
+
/** The acceptance times of `kind` on the relationship inside the window before `when`. */
|
|
34
|
+
export declare const rateCount: (state: Readonly<HolderState>, relId: string, kind: keyof Rates, when: Millis) => number;
|
|
35
|
+
/** The state with one more acceptance of `kind` on the relationship at `when`, the window pruned. */
|
|
36
|
+
export declare function withRate(state: Readonly<HolderState>, relId: string, kind: keyof Rates, when: Millis): HolderState;
|
|
37
|
+
/** The message state without the relationships `relIds` (a departure). */
|
|
38
|
+
export declare function withoutRelationships(state: Readonly<HolderState>, relIds: readonly string[]): HolderState;
|
|
39
|
+
/** Whether the tuple is ready (5.1): a document of its counterpart was accepted on it. */
|
|
40
|
+
export declare const tupleReady: (state: Readonly<HolderState>, label: string) => boolean;
|
|
41
|
+
/** Where a message to the contact goes now, or why it cannot (5010–5030):
|
|
42
|
+
* the first unblocked, ready channel. */
|
|
43
|
+
export declare function messageChannel(state: Readonly<HolderState>, contactId: string): {
|
|
44
|
+
rel: Relationship;
|
|
45
|
+
tuple: Tuple;
|
|
46
|
+
} | Refusal;
|
|
47
|
+
/** The message module createHolder registers. */
|
|
48
|
+
export declare function messageModule(): HolderModule;
|
|
49
|
+
//# sourceMappingURL=holder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"holder.d.ts","sourceRoot":"","sources":["../../src/message/holder.ts"],"names":[],"mappings":"AAwFA,OAAO,KAAK,EAAc,YAAY,EAAiB,OAAO,EAAe,MAAM,cAAc,CAAA;AACjG,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAc9F,eAAO,MAAM,gBAAgB;;;;EAAiG,CAAA;AAE9H,0DAA0D;AAC1D,eAAO,MAAM,WAAW,WAAa,CAAA;AACrC;2DAC2D;AAC3D,eAAO,MAAM,WAAW,KAAK,CAAA;AAE7B,MAAM,WAAW,UAAU;IAAG,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE;AACnE,MAAM,WAAW,SAAS;IAAG,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;AAChF,MAAM,WAAW,SAAS;IAAG,GAAG,EAAE,MAAM,EAAE,CAAA;CAAE;AAM5C,2DAA2D;AAC3D,eAAO,MAAM,UAAU,GAAI,OAAO,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,MAAM,KAAG,OAAiD,CAAA;AAE1H,4EAA4E;AAC5E,eAAO,MAAM,SAAS,GAAI,OAAO,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,MAAM,KAAG,MAAM,GAAG,IAAgD,CAAA;AAEhI,oFAAoF;AACpF,eAAO,MAAM,cAAc,GAAI,OAAO,QAAQ,CAAC,WAAW,CAAC,EAAE,IAAI,MAAM,KAAG,OAGzE,CAAA;AAED,4DAA4D;AAC5D,eAAO,MAAM,WAAW,GAAI,SAAS,SAAS,MAAM,EAAE,EAAE,QAAQ,SAAS,MAAM,EAAE,EAAE,IAAI,OAAO,KAAG,MAAM,EACF,CAAA;AAErG,0FAA0F;AAC1F,eAAO,MAAM,SAAS,GAAI,OAAO,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,MAAM,EAAE,MAAM,MAAM,KAAK,EAAE,MAAM,MAAM,KAAG,MAC2B,CAAA;AAEpI,qGAAqG;AACrG,wBAAgB,QAAQ,CAAE,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAInH;AAED,0EAA0E;AAC1E,wBAAgB,oBAAoB,CAAE,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,CAK1G;AAMD,0FAA0F;AAC1F,eAAO,MAAM,UAAU,GAAI,OAAO,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,MAAM,KAAG,OAA+C,CAAA;AAiBxH;0CAC0C;AAC1C,wBAAgB,cAAc,CAAE,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG,OAAO,CAO9H;AAwLD,iDAAiD;AACjD,wBAAgB,aAAa,IAAK,YAAY,CAS7C"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { activeTuple, entryOf, findContact, liveRel, tupleByLabel } from '../trust/state.js';
|
|
2
|
+
import { tupleByRkid } from '../receive.js';
|
|
3
|
+
import { calOK, iso } from '../core.js';
|
|
4
|
+
import { digestDoc, xRawOfMk } from '../crypto.js';
|
|
5
|
+
import { seal } from '../delivery.js';
|
|
6
|
+
import { INBOX_BOUND, MESSAGE_FUTURE_MS, MESSAGE_LIFETIME_MS, MESSAGE_RATE, MESSAGE_SENDER_LIFETIME_MS, MESSAGE_TYPE, messageKeyOf, messageMac, messageShapeOk, } from '../message.js';
|
|
7
|
+
export const MESSAGE_COMMANDS = Object.freeze({ send: 'message.send', block: 'message.block', take: 'message.take' });
|
|
8
|
+
/** The rate window of Message Tasks 4.2: any 24 hours. */
|
|
9
|
+
export const RATE_WINDOW = 86_400_000;
|
|
10
|
+
/** At most 20 invitations with a new credential digest per relationship
|
|
11
|
+
* and window (RLTP-MSG-4115, Membership RLTP-MT-3105). */
|
|
12
|
+
export const INVITE_RATE = 20;
|
|
13
|
+
const no = (code, ref) => ({ ok: false, code, ...(ref ? { ref } : {}) });
|
|
14
|
+
const refuse = (reason, ref) => ({ ok: false, reason, ...(ref ? { ref } : {}) });
|
|
15
|
+
const cmp = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
|
|
16
|
+
/** Whether the relationship is blocked (RLTP-MSG-6010). */
|
|
17
|
+
export const blockedRel = (state, relId) => state.messages.blocked.includes(relId);
|
|
18
|
+
/** The relationship id the own tuple key `rkid` belongs to now, or null. */
|
|
19
|
+
export const relOfRkid = (state, rkid) => tupleByRkid(state, rkid)?.rel.id ?? null;
|
|
20
|
+
/** Whether any relationship of the entry `id` names (by id or alias) is blocked. */
|
|
21
|
+
export const blockedContact = (state, id) => {
|
|
22
|
+
const c = findContact(state, id);
|
|
23
|
+
return c !== undefined && c.relIds.some((r) => blockedRel(state, r));
|
|
24
|
+
};
|
|
25
|
+
/** The blocked set with `relIds` set or cleared, sorted. */
|
|
26
|
+
export const withBlocked = (blocked, relIds, on) => (on ? [...new Set([...blocked, ...relIds])] : blocked.filter((r) => !relIds.includes(r))).sort(cmp);
|
|
27
|
+
/** The acceptance times of `kind` on the relationship inside the window before `when`. */
|
|
28
|
+
export const rateCount = (state, relId, kind, when) => (Object.hasOwn(state.messages.rates, relId) ? state.messages.rates[relId][kind] : []).filter((t) => t > when - RATE_WINDOW).length;
|
|
29
|
+
/** The state with one more acceptance of `kind` on the relationship at `when`, the window pruned. */
|
|
30
|
+
export function withRate(state, relId, kind, when) {
|
|
31
|
+
const held = Object.hasOwn(state.messages.rates, relId) ? state.messages.rates[relId] : { invites: [], messages: [] };
|
|
32
|
+
const next = { ...held, [kind]: [...held[kind].filter((t) => t > when - RATE_WINDOW), when] };
|
|
33
|
+
return { ...state, messages: { ...state.messages, rates: { ...state.messages.rates, [relId]: next } } };
|
|
34
|
+
}
|
|
35
|
+
/** The message state without the relationships `relIds` (a departure). */
|
|
36
|
+
export function withoutRelationships(state, relIds) {
|
|
37
|
+
if (!relIds.some((r) => blockedRel(state, r) || Object.hasOwn(state.messages.rates, r)))
|
|
38
|
+
return state;
|
|
39
|
+
const rates = { ...state.messages.rates };
|
|
40
|
+
for (const r of relIds)
|
|
41
|
+
delete rates[r];
|
|
42
|
+
return { ...state, messages: { ...state.messages, blocked: state.messages.blocked.filter((r) => !relIds.includes(r)), rates } };
|
|
43
|
+
}
|
|
44
|
+
// ── the message: sending (Section 5) ───────────────────────────────────
|
|
45
|
+
const UUID4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
46
|
+
/** Whether the tuple is ready (5.1): a document of its counterpart was accepted on it. */
|
|
47
|
+
export const tupleReady = (state, label) => state.messages.ready.includes(label);
|
|
48
|
+
/** The relationships a message to the entry may go on: live, their active
|
|
49
|
+
* head feeding the entry (5010), in the entry's order. */
|
|
50
|
+
function channelsOf(state, contactId) {
|
|
51
|
+
const c = findContact(state, contactId);
|
|
52
|
+
if (!c)
|
|
53
|
+
return null;
|
|
54
|
+
const ids = new Set([c.id, ...c.aliases]);
|
|
55
|
+
const out = [];
|
|
56
|
+
for (const id of c.relIds) {
|
|
57
|
+
const rel = state.relationships[id];
|
|
58
|
+
const t = rel && liveRel(rel) ? activeTuple(rel) : undefined;
|
|
59
|
+
if (t && !t.deactivated && ids.has(t.entryId))
|
|
60
|
+
out.push({ rel, tuple: t });
|
|
61
|
+
}
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
/** Where a message to the contact goes now, or why it cannot (5010–5030):
|
|
65
|
+
* the first unblocked, ready channel. */
|
|
66
|
+
export function messageChannel(state, contactId) {
|
|
67
|
+
const all = channelsOf(state, contactId);
|
|
68
|
+
if (all === null)
|
|
69
|
+
return no('unknown-contact');
|
|
70
|
+
if (!all.length)
|
|
71
|
+
return no('no-own-channel', 'RLTP-MSG-5010');
|
|
72
|
+
const open = all.filter((x) => !blockedRel(state, x.rel.id));
|
|
73
|
+
if (!open.length)
|
|
74
|
+
return no('blocked', 'RLTP-MSG-5030');
|
|
75
|
+
return open.find((x) => tupleReady(state, x.tuple.ownPairLabel)) ?? no('not-ready', 'RLTP-MSG-5020');
|
|
76
|
+
}
|
|
77
|
+
const isRefusal = (x) => x?.ok === false;
|
|
78
|
+
const sendDef = {
|
|
79
|
+
human: true,
|
|
80
|
+
async prepare(ctx, input) {
|
|
81
|
+
if (typeof input?.contactId !== 'string' || typeof input.text !== 'string')
|
|
82
|
+
throw new TypeError('message.send needs {contactId, text}');
|
|
83
|
+
const n = [...input.text].length;
|
|
84
|
+
if (n < 1 || n > 4096 || (input.replyTo !== undefined && (typeof input.replyTo !== 'string' || !UUID4.test(input.replyTo))))
|
|
85
|
+
return no('message-invalid', 'RLTP-MSG-3020');
|
|
86
|
+
const s = ctx.snapshot;
|
|
87
|
+
const ch = messageChannel(s, input.contactId);
|
|
88
|
+
if (isRefusal(ch))
|
|
89
|
+
return ch;
|
|
90
|
+
const S = ctx.crypto.subtle;
|
|
91
|
+
const own = await ctx.keys.anchorOf(ch.tuple.ownPairLabel);
|
|
92
|
+
const raw = xRawOfMk(ch.tuple.counterpartKeyAgreement);
|
|
93
|
+
const a = raw ? await ctx.keys.agree(ch.tuple.rkid, raw, ctx.release) : null;
|
|
94
|
+
if (!a || a.status !== 'available')
|
|
95
|
+
return no('no-own-channel', 'RLTP-MSG-3110');
|
|
96
|
+
const key = await messageKeyOf(a.shared, own.anchor, ch.tuple.counterpartAnchor, S);
|
|
97
|
+
// sentAt in whole seconds (3030), the sender's clock
|
|
98
|
+
const sec = Math.floor(ctx.when / 1000) * 1000;
|
|
99
|
+
const body = {
|
|
100
|
+
type: 'message@1', mid: ctx.entropy.id('message.mid'), sentAt: iso(sec), text: input.text,
|
|
101
|
+
...(input.replyTo !== undefined ? { replyTo: input.replyTo } : {}),
|
|
102
|
+
};
|
|
103
|
+
const payload = { body, proof: { mac: await messageMac(key, body, S) } };
|
|
104
|
+
const doc = {
|
|
105
|
+
id: ctx.entropy.id('doc.id'), type: MESSAGE_TYPE, issuer: own.anchor, recipient: ch.tuple.counterpartAnchor,
|
|
106
|
+
threadId: ctx.entropy.id('thread.id'), issuedAt: iso(ctx.when), payload,
|
|
107
|
+
};
|
|
108
|
+
const envelope = await seal(doc, ch.tuple.counterpartKeyAgreement, { ephSeed: ctx.entropy.bytes('seal.eph', 32), nonce: ctx.entropy.bytes('seal.nonce', 12) }, S);
|
|
109
|
+
const contactId = entryOf(s, ch.rel)?.id ?? ch.rel.contactId;
|
|
110
|
+
return {
|
|
111
|
+
mid: body.mid, contactId,
|
|
112
|
+
draft: {
|
|
113
|
+
digest: await digestDoc(doc, S), envelope, type: MESSAGE_TYPE, threadId: doc.threadId,
|
|
114
|
+
recipient: { contactId, rkid: ch.tuple.rkid, keyAgreement: ch.tuple.counterpartKeyAgreement },
|
|
115
|
+
// the sender's give-up a day before the age bound (5110, Delivery 7020)
|
|
116
|
+
expiresAt: sec + MESSAGE_SENDER_LIFETIME_MS,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
apply(state, prepared) {
|
|
121
|
+
const p = prepared.value;
|
|
122
|
+
if (isRefusal(p))
|
|
123
|
+
return p;
|
|
124
|
+
return { state: state, outbound: [p.draft], events: [{ type: 'message.sent', contactId: p.contactId, mid: p.mid, digest: p.draft.digest }] };
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
// ── the message: reception (Section 4) ─────────────────────────────────
|
|
128
|
+
/** The inbox entries of the relationship `relId` (through their tuples now). */
|
|
129
|
+
const inboxCount = (state, relId) => Object.values(state.messages.inbox).filter((e) => tupleByLabel(state, e.tuple)?.rel.id === relId).length;
|
|
130
|
+
const messageTask = {
|
|
131
|
+
proof: 'absent',
|
|
132
|
+
// stage 7: the closed form (4010); the calendar is a verifier's check (3030)
|
|
133
|
+
decode(p) {
|
|
134
|
+
if (!messageShapeOk(p))
|
|
135
|
+
return refuse('malformed', 'RLTP-MSG-4010');
|
|
136
|
+
return calOK(p.body.sentAt) ? p : refuse('validation-failed', 'RLTP-MSG-3030');
|
|
137
|
+
},
|
|
138
|
+
async prepare(ctx, doc, arr) {
|
|
139
|
+
const s = ctx.snapshot;
|
|
140
|
+
const S = ctx.crypto.subtle;
|
|
141
|
+
const at = tupleByRkid(s, arr.rkid);
|
|
142
|
+
// the MAC under k_msg of the arrival tuple, issuer to recipient (4020, 3110, 3120)
|
|
143
|
+
const raw = xRawOfMk(at.tuple.counterpartKeyAgreement);
|
|
144
|
+
const a = raw ? await ctx.keys.agree(arr.rkid, raw, ctx.release) : null;
|
|
145
|
+
if (!a || a.status !== 'available')
|
|
146
|
+
return refuse('validation-failed', 'RLTP-MSG-4020');
|
|
147
|
+
let key;
|
|
148
|
+
try {
|
|
149
|
+
key = await messageKeyOf(a.shared, doc.issuer, doc.recipient, S);
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return refuse('validation-failed', 'RLTP-MSG-3120');
|
|
153
|
+
}
|
|
154
|
+
if ((await messageMac(key, doc.payload.body, S)) !== doc.payload.proof.mac)
|
|
155
|
+
return refuse('validation-failed', 'RLTP-MSG-4020');
|
|
156
|
+
// the bounds (4110), counted before the block (4130): transient (4120)
|
|
157
|
+
const relId = at.rel.id;
|
|
158
|
+
if (rateCount(s, relId, 'messages', ctx.when) >= MESSAGE_RATE)
|
|
159
|
+
return refuse('rate-limited', 'RLTP-MSG-4110');
|
|
160
|
+
// the inbox bound is counted before the block too (4130): a new mid
|
|
161
|
+
// meets the entries held, blocked or not; once it passes, a block
|
|
162
|
+
// discards it, an entry taken over at once
|
|
163
|
+
const known = s.messages.records[at.tuple.ownPairLabel]?.[doc.payload.body.mid] !== undefined;
|
|
164
|
+
if (!known && inboxCount(s, relId) >= INBOX_BOUND)
|
|
165
|
+
return refuse('rate-limited', 'RLTP-MSG-4110');
|
|
166
|
+
return { bodyDigest: await digestDoc(doc.payload.body, S) };
|
|
167
|
+
},
|
|
168
|
+
// stage 9, on t_ref = arr.when (raised to lastWhen, the mark of 4060)
|
|
169
|
+
apply(state, prepared, doc, arr) {
|
|
170
|
+
const at = tupleByRkid(state, arr.rkid);
|
|
171
|
+
const label = at.tuple.ownPairLabel;
|
|
172
|
+
const relId = at.rel.id;
|
|
173
|
+
const body = doc.payload.body;
|
|
174
|
+
const tRef = arr.when;
|
|
175
|
+
const sentAt = Date.parse(body.sentAt);
|
|
176
|
+
if (sentAt + MESSAGE_LIFETIME_MS < tRef)
|
|
177
|
+
return refuse('stale-issuance', 'RLTP-MSG-4040');
|
|
178
|
+
if (sentAt > tRef + MESSAGE_FUTURE_MS)
|
|
179
|
+
return refuse('validation-failed', 'RLTP-MSG-4050');
|
|
180
|
+
const { bodyDigest } = prepared.value;
|
|
181
|
+
const held = Object.hasOwn(state.messages.records, label) && Object.hasOwn(state.messages.records[label], body.mid) ? state.messages.records[label][body.mid] : undefined;
|
|
182
|
+
if (held && held.bodyDigest !== bodyDigest)
|
|
183
|
+
return refuse('validation-failed', 'RLTP-MSG-4330');
|
|
184
|
+
// the rate counts every new document digest accepted, before the block (4110, 4130)
|
|
185
|
+
let next = withRate(state, relId, 'messages', tRef);
|
|
186
|
+
// a known mid with its body: no new effect, a fresh ack (4320)
|
|
187
|
+
if (held)
|
|
188
|
+
return { state: next };
|
|
189
|
+
const records = { ...next.messages.records, [label]: { ...(next.messages.records[label] ?? {}), [body.mid]: { bodyDigest, sentAt } } };
|
|
190
|
+
next = { ...next, messages: { ...next.messages, records } };
|
|
191
|
+
// under a block: discard — the record, the cache entry and the ack, nothing else (6210, 6220)
|
|
192
|
+
if (blockedRel(state, relId))
|
|
193
|
+
return { state: next };
|
|
194
|
+
const entry = { id: arr.digest, tuple: label, mid: body.mid, body: body, receivedAt: tRef, displayAt: Math.min(sentAt, tRef) };
|
|
195
|
+
const contactId = entryOf(state, at.rel)?.id ?? at.rel.contactId;
|
|
196
|
+
return {
|
|
197
|
+
state: { ...next, messages: { ...next.messages, inbox: { ...next.messages.inbox, [entry.id]: entry } } },
|
|
198
|
+
events: [{ type: 'message.received', contactId, inboxId: entry.id }],
|
|
199
|
+
};
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
/** The application took inbox entries over durably (4420). */
|
|
203
|
+
const takeDef = {
|
|
204
|
+
human: false,
|
|
205
|
+
apply(state, _p, input) {
|
|
206
|
+
if (!Array.isArray(input?.ids) || !input.ids.every((x) => typeof x === 'string'))
|
|
207
|
+
throw new TypeError('message.take needs {ids: string[]}');
|
|
208
|
+
const gone = input.ids.filter((id) => Object.hasOwn(state.messages.inbox, id));
|
|
209
|
+
if (!gone.length)
|
|
210
|
+
return { state: state };
|
|
211
|
+
const inbox = { ...state.messages.inbox };
|
|
212
|
+
for (const id of gone)
|
|
213
|
+
delete inbox[id];
|
|
214
|
+
// the completion record stays (4350)
|
|
215
|
+
return { state: { ...state, messages: { ...state.messages, inbox } } };
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
/** The tuple a counterpart's document was accepted on is ready (5.1). */
|
|
219
|
+
function markReady(state, doc, arr) {
|
|
220
|
+
const at = tupleByRkid(state, arr.rkid);
|
|
221
|
+
if (!at || doc.issuer !== at.tuple.counterpartAnchor || tupleReady(state, at.tuple.ownPairLabel))
|
|
222
|
+
return state;
|
|
223
|
+
const ready = [...state.messages.ready, at.tuple.ownPairLabel].sort(cmp);
|
|
224
|
+
return { ...state, messages: { ...state.messages, ready } };
|
|
225
|
+
}
|
|
226
|
+
/** The completion record's retention (4340): an entry leaves once
|
|
227
|
+
* t_ref (tick's time, written as the mark) lies after sentAt + H, or once
|
|
228
|
+
* its tuple is deactivated or gone; ready marks of tuples gone leave. */
|
|
229
|
+
function retainMessages(state, when) {
|
|
230
|
+
let changed = false;
|
|
231
|
+
const records = {};
|
|
232
|
+
for (const [label, rec] of Object.entries(state.messages.records)) {
|
|
233
|
+
const t = tupleByLabel(state, label);
|
|
234
|
+
if (!t || t.tuple.deactivated) {
|
|
235
|
+
changed = true;
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
const keep = Object.entries(rec).filter(([, e]) => !(e.sentAt + MESSAGE_LIFETIME_MS < when));
|
|
239
|
+
if (keep.length !== Object.keys(rec).length)
|
|
240
|
+
changed = true;
|
|
241
|
+
if (keep.length)
|
|
242
|
+
records[label] = Object.fromEntries(keep);
|
|
243
|
+
}
|
|
244
|
+
const ready = state.messages.ready.filter((l) => tupleByLabel(state, l) !== null);
|
|
245
|
+
if (ready.length !== state.messages.ready.length)
|
|
246
|
+
changed = true;
|
|
247
|
+
return changed ? { ...state, messages: { ...state.messages, records, ready } } : state;
|
|
248
|
+
}
|
|
249
|
+
/** When retainMessages lets an entry go by time (the timer contract). */
|
|
250
|
+
function messageDeadlines(state) {
|
|
251
|
+
const out = [];
|
|
252
|
+
for (const rec of Object.values(state.messages.records)) {
|
|
253
|
+
let first = Infinity;
|
|
254
|
+
for (const e of Object.values(rec))
|
|
255
|
+
first = Math.min(first, e.sentAt + MESSAGE_LIFETIME_MS + 1);
|
|
256
|
+
if (first !== Infinity)
|
|
257
|
+
out.push(first);
|
|
258
|
+
}
|
|
259
|
+
return out;
|
|
260
|
+
}
|
|
261
|
+
// ── the block act (Section 6.1) ────────────────────────────────────────
|
|
262
|
+
const blockDef = {
|
|
263
|
+
human: true,
|
|
264
|
+
apply(state, _p, input) {
|
|
265
|
+
if (typeof input?.contactId !== 'string' || typeof input.blocked !== 'boolean')
|
|
266
|
+
throw new TypeError('message.block needs {contactId, blocked}');
|
|
267
|
+
const c = findContact(state, input.contactId);
|
|
268
|
+
if (!c)
|
|
269
|
+
return no('unknown-contact');
|
|
270
|
+
// every relationship of the entry (6020); unblocking deletes nothing
|
|
271
|
+
// else and surfaces nothing (6510)
|
|
272
|
+
const blocked = withBlocked(state.messages.blocked, c.relIds, input.blocked);
|
|
273
|
+
return {
|
|
274
|
+
state: { ...state, messages: { ...state.messages, blocked } },
|
|
275
|
+
events: [{ type: 'contact.blocked', contactId: c.id, blocked: input.blocked }],
|
|
276
|
+
};
|
|
277
|
+
},
|
|
278
|
+
};
|
|
279
|
+
/** The message module createHolder registers. */
|
|
280
|
+
export function messageModule() {
|
|
281
|
+
return Object.freeze({
|
|
282
|
+
name: 'message',
|
|
283
|
+
commands: Object.freeze({ [MESSAGE_COMMANDS.send]: sendDef, [MESSAGE_COMMANDS.block]: blockDef, [MESSAGE_COMMANDS.take]: takeDef }),
|
|
284
|
+
tasks: Object.freeze({ [MESSAGE_TYPE]: messageTask }),
|
|
285
|
+
accepted: markReady,
|
|
286
|
+
retain: retainMessages,
|
|
287
|
+
deadlines: messageDeadlines,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=holder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"holder.js","sourceRoot":"","sources":["../../src/message/holder.ts"],"names":[],"mappings":"AA2FA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAC5F,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AACrC,OAAO,EACL,WAAW,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,YAAY,EAAE,0BAA0B,EAAE,YAAY,EAC3G,YAAY,EAAE,UAAU,EAAE,cAAc,GACzC,MAAM,eAAe,CAAA;AAGtB,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,cAAc,EAAW,CAAC,CAAA;AAE9H,0DAA0D;AAC1D,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAA;AACrC;2DAC2D;AAC3D,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAA;AAM7B,MAAM,EAAE,GAAG,CAAC,IAAqB,EAAE,GAAY,EAAW,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;AAC3G,MAAM,MAAM,GAAG,CAAC,MAA6B,EAAE,GAAY,EAAe,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;AAC7H,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAE1E,2DAA2D;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAA4B,EAAE,KAAa,EAAW,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAE1H,4EAA4E;AAC5E,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAA4B,EAAE,IAAY,EAAiB,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,IAAI,CAAA;AAEhI,oFAAoF;AACpF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAA4B,EAAE,EAAU,EAAW,EAAE;IAClF,MAAM,CAAC,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAChC,OAAO,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAA;AACtE,CAAC,CAAA;AAED,4DAA4D;AAC5D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAA0B,EAAE,MAAyB,EAAE,EAAW,EAAY,EAAE,CAC1G,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAErG,0FAA0F;AAC1F,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAA4B,EAAE,KAAa,EAAE,IAAiB,EAAE,IAAY,EAAU,EAAE,CAChH,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,GAAG,WAAW,CAAC,CAAC,MAAM,CAAA;AAEpI,qGAAqG;AACrG,MAAM,UAAU,QAAQ,CAAE,KAA4B,EAAE,KAAa,EAAE,IAAiB,EAAE,IAAY;IACpG,MAAM,IAAI,GAAU,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IAC5H,MAAM,IAAI,GAAU,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,GAAG,WAAW,CAAC,EAAE,IAAI,CAAC,EAAE,CAAA;IACpG,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,EAAE,EAAiB,CAAA;AACxH,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,oBAAoB,CAAE,KAA4B,EAAE,MAAyB;IAC3F,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,KAAoB,CAAA;IACpH,MAAM,KAAK,GAAG,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;IACzC,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAA;IACvC,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAiB,CAAA;AAChJ,CAAC;AAED,0EAA0E;AAE1E,MAAM,KAAK,GAAG,uEAAuE,CAAA;AAErF,0FAA0F;AAC1F,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAA4B,EAAE,KAAa,EAAW,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAExH;2DAC2D;AAC3D,SAAS,UAAU,CAAE,KAA4B,EAAE,SAAiB;IAClE,MAAM,CAAC,GAAG,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IACvC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAA;IACnB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAA;IACzC,MAAM,GAAG,GAA+C,EAAE,CAAA;IAC1D,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,CAAA;QACnC,MAAM,CAAC,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAC5D,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;IAC5E,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;0CAC0C;AAC1C,MAAM,UAAU,cAAc,CAAE,KAA4B,EAAE,SAAiB;IAC7E,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IACxC,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC,iBAAiB,CAAC,CAAA;IAC9C,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAA;IAC7D,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;IAC5D,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC,CAAA;IACvD,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,eAAe,CAAC,CAAA;AACtG,CAAC;AAID,MAAM,SAAS,GAAG,CAAC,CAAU,EAAgB,EAAE,CAAE,CAAa,EAAE,EAAE,KAAK,KAAK,CAAA;AAE5E,MAAM,OAAO,GAA8C;IACzD,KAAK,EAAE,IAAI;IACX,KAAK,CAAC,OAAO,CAAE,GAAG,EAAE,KAAK;QACvB,IAAI,OAAO,KAAK,EAAE,SAAS,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,IAAI,SAAS,CAAC,sCAAsC,CAAC,CAAA;QACvI,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAA;QAChC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAA;QAC1K,MAAM,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAA;QACtB,MAAM,EAAE,GAAG,cAAc,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAA;QAC7C,IAAI,SAAS,CAAC,EAAE,CAAC;YAAE,OAAO,EAAE,CAAA;QAC5B,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAA;QAC3B,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;QAC1D,MAAM,GAAG,GAAG,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAA;QACtD,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAC5E,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW;YAAE,OAAO,EAAE,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAA;QAChF,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAA;QACnF,qDAAqD;QACrD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,IAAI,CAAA;QAC9C,MAAM,IAAI,GAAgB;YACxB,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI;YACzF,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnE,CAAA;QACD,MAAM,OAAO,GAAmB,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAA;QACxF,MAAM,GAAG,GAAG;YACV,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,KAAK,CAAC,iBAAiB;YAC3G,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO;SACxE,CAAA;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAY,EAAE,EAAE,CAAC,KAAK,CAAC,uBAAuB,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;QAC1K,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,SAAS,CAAA;QAC5D,OAAO;YACL,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS;YACxB,KAAK,EAAE;gBACL,MAAM,EAAE,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACrF,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,CAAC,KAAK,CAAC,uBAAuB,EAAE;gBAC7F,wEAAwE;gBACxE,SAAS,EAAE,GAAG,GAAG,0BAA0B;aAC5C;SACF,CAAA;IACH,CAAC;IACD,KAAK,CAAE,KAAK,EAAE,QAAQ;QACpB,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAA;QACxB,IAAI,SAAS,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAA;QAC1B,OAAO,EAAE,KAAK,EAAE,KAAoB,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAA;IAC7J,CAAC;CACF,CAAA;AAED,0EAA0E;AAE1E,gFAAgF;AAChF,MAAM,UAAU,GAAG,CAAC,KAA4B,EAAE,KAAa,EAAU,EAAE,CACzE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,MAAM,CAAA;AAE1G,MAAM,WAAW,GAAwD;IACvE,KAAK,EAAE,QAAQ;IACf,6EAA6E;IAC7E,MAAM,CAAE,CAAC;QACP,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;YAAE,OAAO,MAAM,CAAC,WAAW,EAAE,eAAe,CAAC,CAAA;QACnE,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAA;IAChF,CAAC;IACD,KAAK,CAAC,OAAO,CAAE,GAAG,EAAE,GAAG,EAAE,GAAG;QAC1B,MAAM,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAA;QACtB,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAA;QAC3B,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,CAAE,CAAA;QACpC,mFAAmF;QACnF,MAAM,GAAG,GAAG,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAA;QACtD,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QACvE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW;YAAE,OAAO,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAA;QACvF,IAAI,GAAe,CAAA;QACnB,IAAI,CAAC;YAAC,GAAG,GAAG,MAAM,YAAY,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAA;QAAC,CAAC;QACtI,IAAI,CAAC,MAAM,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG;YAAE,OAAO,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAA;QAC/H,uEAAuE;QACvE,MAAM,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAA;QACvB,IAAI,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,YAAY;YAAE,OAAO,MAAM,CAAC,cAAc,EAAE,eAAe,CAAC,CAAA;QAC7G,oEAAoE;QACpE,kEAAkE;QAClE,2CAA2C;QAC3C,MAAM,KAAK,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,SAAS,CAAA;QAC7F,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,WAAW;YAAE,OAAO,MAAM,CAAC,cAAc,EAAE,eAAe,CAAC,CAAA;QACjG,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAA;IAC7D,CAAC;IACD,sEAAsE;IACtE,KAAK,CAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG;QAC9B,MAAM,EAAE,GAAG,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAE,CAAA;QACxC,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,CAAA;QACnC,MAAM,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAA;QACvB,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAA;QAC7B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAA;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACtC,IAAI,MAAM,GAAG,mBAAmB,GAAG,IAAI;YAAE,OAAO,MAAM,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAA;QACzF,IAAI,MAAM,GAAG,IAAI,GAAG,iBAAiB;YAAE,OAAO,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAA;QAC1F,MAAM,EAAE,UAAU,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAA;QACrC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QACzK,IAAI,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,UAAU;YAAE,OAAO,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAA;QAC/F,oFAAoF;QACpF,IAAI,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,CAAA;QACnD,+DAA+D;QAC/D,IAAI,IAAI;YAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;QAChC,MAAM,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;QACtI,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAA;QAC3D,8FAA8F;QAC9F,IAAI,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;QACpD,MAAM,KAAK,GAAe,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,IAA6B,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAA;QACnK,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,SAAS,CAAA;QAChE,OAAO;YACL,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;YACxG,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC;SACrE,CAAA;IACH,CAAC;CACF,CAAA;AAED,8DAA8D;AAC9D,MAAM,OAAO,GAAgC;IAC3C,KAAK,EAAE,KAAK;IACZ,KAAK,CAAE,KAAK,EAAE,EAAE,EAAE,KAAK;QACrB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,oCAAoC,CAAC,CAAA;QAC3I,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAA;QAC9E,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,KAAK,EAAE,KAAoB,EAAE,CAAA;QACxD,MAAM,KAAK,GAAG,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;QACzC,KAAK,MAAM,EAAE,IAAI,IAAI;YAAE,OAAO,KAAK,CAAC,EAAE,CAAC,CAAA;QACvC,qCAAqC;QACrC,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAA;IACxE,CAAC;CACF,CAAA;AAED,yEAAyE;AACzE,SAAS,SAAS,CAAE,KAA4B,EAAE,GAAqB,EAAE,GAAY;IACnF,MAAM,EAAE,GAAG,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;IACvC,IAAI,CAAC,EAAE,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE,CAAC,KAAK,CAAC,iBAAiB,IAAI,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC;QAAE,OAAO,KAAoB,CAAA;IAC7H,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACxE,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAA;AAC7D,CAAC;AAED;;0EAE0E;AAC1E,SAAS,cAAc,CAAE,KAA4B,EAAE,IAAY;IACjE,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,MAAM,OAAO,GAAuC,EAAE,CAAA;IACtD,KAAK,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAClE,MAAM,CAAC,GAAG,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;QACpC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YAAC,OAAO,GAAG,IAAI,CAAC;YAAC,SAAQ;QAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAAC,CAAC,CAAA;QAC5F,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM;YAAE,OAAO,GAAG,IAAI,CAAA;QAC3D,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IAC5D,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;IACjF,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,GAAG,IAAI,CAAA;IAChE,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,KAAoB,CAAA;AACvG,CAAC;AAED,yEAAyE;AACzE,SAAS,gBAAgB,CAAE,KAA4B;IACrD,MAAM,GAAG,GAAa,EAAE,CAAA;IACxB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACxD,IAAI,KAAK,GAAG,QAAQ,CAAA;QACpB,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;YAAE,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,GAAG,mBAAmB,GAAG,CAAC,CAAC,CAAA;QAC/F,IAAI,KAAK,KAAK,QAAQ;YAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACzC,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,0EAA0E;AAE1E,MAAM,QAAQ,GAAiC;IAC7C,KAAK,EAAE,IAAI;IACX,KAAK,CAAE,KAAK,EAAE,EAAE,EAAE,KAAK;QACrB,IAAI,OAAO,KAAK,EAAE,SAAS,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,SAAS;YAAE,MAAM,IAAI,SAAS,CAAC,0CAA0C,CAAC,CAAA;QAC/I,MAAM,CAAC,GAAG,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,CAAA;QAC7C,IAAI,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC,iBAAiB,CAAC,CAAA;QACpC,qEAAqE;QACrE,mCAAmC;QACnC,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;QAC5E,OAAO;YACL,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE;YAC7D,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;SAC/E,CAAA;IACH,CAAC;CACF,CAAA;AAED,iDAAiD;AACjD,MAAM,UAAU,aAAa;IAC3B,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;QACnI,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;QACrD,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,cAAc;QACtB,SAAS,EAAE,gBAAgB;KAC5B,CAAC,CAAA;AACJ,CAAC","sourcesContent":["// message/holder — Message Tasks 0.1 on the holder (lib 0.5.0): the\n// message (Sections 3 to 5), the block of a relationship (Section 6) and\n// the rates per relationship (4.2).\n//\n// What it registers (messageModule):\n// human acts message.send {contactId, text, replyTo?} a message@1 on\n// the active head of a ready, unblocked relationship of the\n// contact (5010–5030), its document carrying the sender\n// lifetime sentAt + H − P1D (5110, Delivery RLTP-DEL-7020);\n// event message.sent {contactId, mid, digest}\n// message.block {contactId, blocked} sets or clears the\n// block on every relationship of the contact's entry\n// (RLTP-MSG-6020); event contact.blocked\n// not human message.take {ids} the application took the inbox\n// entries over durably (4420): they leave the inbox\n// task message/0.1 (proof absent, designated-verifier: a MAC ack)\n// accepted the arrival tuple is ready once a document of its\n// counterpart was accepted on it (5.1)\n// retain completion-record entries past sentAt + H, or of a tuple\n// deactivated or gone (4340); ready marks of tuples gone\n//\n// Reception (Section 4): stage 7 the schema (4010), stage 8 the calendar\n// (3030), the MAC under k_msg of the arrival tuple (4020; issuer and\n// recipient are the tuple's pair anchors by the core's binding, which also\n// refuses a tuple that is no active head, 4030), and the bounds of 4110\n// counted before the block (4130): failed(rate-limited), transient (4120,\n// 4140). Stage 9, on t_ref = the receive's time raised to `lastWhen`: the\n// age bound (4040, failed(stale-issuance)) and the future bound (4050),\n// the completion record (4320: no new effect and a fresh ack; 4330: a\n// different body under a known mid is validation-failed), then the\n// defined effect in one transaction with the cache entry and the ack\n// (4210): the record entry, and an inbox entry unless the relationship is\n// blocked (6210, 6220: discard).\n//\n// What the other modules read through here (pure):\n// blockedRel(state, relId) the block of one relationship (6010)\n// relOfRkid(state, rkid) the relationship an own tuple key belongs\n// to now, through its tuple (attribution,\n// 6110; Membership RLTP-MT-3940)\n// rateCount / withRate the acceptance times a rate counts in the\n// 24 hours before `when` (4110, 4115)\n// blockedContact(state, id) whether any relationship of an entry is\n// blocked (the outbound refusal of 6410)\n//\n// Choices this file makes where the specification leaves them open:\n// - the time mark of 4060 is the engine's `lastWhen`: never lowered,\n// written by every commit, and read once per transaction (`when` is\n// raised to it); the CAS commits only on the state it read, so an\n// acceptance and a deletion that race are serialized and the later one\n// decides on the mark the earlier wrote (#103)\n// - readiness (5020) is a refusal, not a queue: message.send answers\n// `not-ready` and the application keeps the message unsent until the\n// contact view says canMessage; the library holds no drafts\n// - the completion record is per tuple and inbound direction (4310), as\n// the rule says: after a chaining, a body sent again on the new head's\n// tuple, under its own key, is a new message there — the guarantee of\n// one effect per mid holds per tuple, not per relationship\n// - replyTo (5120) is the application's: the library keeps no history of\n// sent mids to check it against, and a receiver never rejects it\n// - the block is kept beside the relationships, by relationship id\n// (`messages.blocked`): the chain's id survives a chaining (6030: the\n// chain keeps its block, and takes the block of the fresh relationship\n// it absorbs, trust/continuity.ts) and stays with the relationship through a\n// merge and a split; trust/entries.ts sets it on every relationship of\n// a merged entry where one held it (6030) and drops it with a departed\n// relationship\n// - the lock keys (Delivery RLTP-DEL-6210–6230, Message Tasks 4230,\n// 4240, 6330): the engine serializes every operation of a holder in\n// one queue and commits by CAS over the whole state, re-entering at\n// stage 1 on a conflict (receive.ts), which holds every key a rule\n// names and decides on the state read after the wait\n// - a rate keeps only the times inside the window, pruned when it is\n// written; at most the bound's number of entries per relationship\n// - the inbox bound counts the entries of the relationship the arrival\n// tuple belongs to now, before the block (4130); a message whose mid\n// the record holds adds no entry and is not refused by it; under a\n// block a message that passed it is discarded, an entry taken over at\n// once\n// - readiness (5.1) is marked by the accepted hook for every unique\n// document of the counterpart on the arrival tuple, its task\n// documents and its verified delivery-acks alike\n// - which types a block treats (Delivery RLTP-DEL-6245): message/0.1\n// (Message Tasks), membership-invite/0.2 and the prelude reply\n// (Membership 0.20, RLTP-MT-3115, 3975). The Trust Layer types of the\n// table of 6.3 (the introduction's, the profile, the stars, the\n// anchor mapping) are evaluated as without a block until the Trust\n// Layer's casting takes the change up (RLTP-MSG-6240); the views mark\n// a blocked contact so an application shows nothing of it (6230)\nimport type { CommandDef, HolderModule, OutboundDraft, Refusal, TaskHandler } from '../engine.js'\nimport type { HolderState, InboxEntry, Millis, Rates, Relationship, Tuple } from '../state.js'\nimport type { JsonObject } from '../core.js'\nimport { activeTuple, entryOf, findContact, liveRel, tupleByLabel } from '../trust/state.js'\nimport { tupleByRkid } from '../receive.js'\nimport type { Arrival, ReceivedDocument, TaskRefusal } from '../receive.js'\nimport { calOK, iso } from '../core.js'\nimport { digestDoc, xRawOfMk } from '../crypto.js'\nimport { seal } from '../delivery.js'\nimport {\n INBOX_BOUND, MESSAGE_FUTURE_MS, MESSAGE_LIFETIME_MS, MESSAGE_RATE, MESSAGE_SENDER_LIFETIME_MS, MESSAGE_TYPE,\n messageKeyOf, messageMac, messageShapeOk,\n} from '../message.js'\nimport type { MessageBody, MessagePayload } from '../message.js'\n\nexport const MESSAGE_COMMANDS = Object.freeze({ send: 'message.send', block: 'message.block', take: 'message.take' } as const)\n\n/** The rate window of Message Tasks 4.2: any 24 hours. */\nexport const RATE_WINDOW = 86_400_000\n/** At most 20 invitations with a new credential digest per relationship\n * and window (RLTP-MSG-4115, Membership RLTP-MT-3105). */\nexport const INVITE_RATE = 20\n\nexport interface BlockInput { contactId: string, blocked: boolean }\nexport interface SendInput { contactId: string, text: string, replyTo?: string }\nexport interface TakeInput { ids: string[] }\n\nconst no = (code: Refusal['code'], ref?: string): Refusal => ({ ok: false, code, ...(ref ? { ref } : {}) })\nconst refuse = (reason: TaskRefusal['reason'], ref?: string): TaskRefusal => ({ ok: false, reason, ...(ref ? { ref } : {}) })\nconst cmp = (a: string, b: string): number => (a < b ? -1 : a > b ? 1 : 0)\n\n/** Whether the relationship is blocked (RLTP-MSG-6010). */\nexport const blockedRel = (state: Readonly<HolderState>, relId: string): boolean => state.messages.blocked.includes(relId)\n\n/** The relationship id the own tuple key `rkid` belongs to now, or null. */\nexport const relOfRkid = (state: Readonly<HolderState>, rkid: string): string | null => tupleByRkid(state, rkid)?.rel.id ?? null\n\n/** Whether any relationship of the entry `id` names (by id or alias) is blocked. */\nexport const blockedContact = (state: Readonly<HolderState>, id: string): boolean => {\n const c = findContact(state, id)\n return c !== undefined && c.relIds.some((r) => blockedRel(state, r))\n}\n\n/** The blocked set with `relIds` set or cleared, sorted. */\nexport const withBlocked = (blocked: readonly string[], relIds: readonly string[], on: boolean): string[] =>\n (on ? [...new Set([...blocked, ...relIds])] : blocked.filter((r) => !relIds.includes(r))).sort(cmp)\n\n/** The acceptance times of `kind` on the relationship inside the window before `when`. */\nexport const rateCount = (state: Readonly<HolderState>, relId: string, kind: keyof Rates, when: Millis): number =>\n (Object.hasOwn(state.messages.rates, relId) ? state.messages.rates[relId][kind] : []).filter((t) => t > when - RATE_WINDOW).length\n\n/** The state with one more acceptance of `kind` on the relationship at `when`, the window pruned. */\nexport function withRate (state: Readonly<HolderState>, relId: string, kind: keyof Rates, when: Millis): HolderState {\n const held: Rates = Object.hasOwn(state.messages.rates, relId) ? state.messages.rates[relId] : { invites: [], messages: [] }\n const next: Rates = { ...held, [kind]: [...held[kind].filter((t) => t > when - RATE_WINDOW), when] }\n return { ...state, messages: { ...state.messages, rates: { ...state.messages.rates, [relId]: next } } } as HolderState\n}\n\n/** The message state without the relationships `relIds` (a departure). */\nexport function withoutRelationships (state: Readonly<HolderState>, relIds: readonly string[]): HolderState {\n if (!relIds.some((r) => blockedRel(state, r) || Object.hasOwn(state.messages.rates, r))) return state as HolderState\n const rates = { ...state.messages.rates }\n for (const r of relIds) delete rates[r]\n return { ...state, messages: { ...state.messages, blocked: state.messages.blocked.filter((r) => !relIds.includes(r)), rates } } as HolderState\n}\n\n// ── the message: sending (Section 5) ───────────────────────────────────\n\nconst UUID4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/\n\n/** Whether the tuple is ready (5.1): a document of its counterpart was accepted on it. */\nexport const tupleReady = (state: Readonly<HolderState>, label: string): boolean => state.messages.ready.includes(label)\n\n/** The relationships a message to the entry may go on: live, their active\n * head feeding the entry (5010), in the entry's order. */\nfunction channelsOf (state: Readonly<HolderState>, contactId: string): Array<{ rel: Relationship, tuple: Tuple }> | null {\n const c = findContact(state, contactId)\n if (!c) return null\n const ids = new Set([c.id, ...c.aliases])\n const out: Array<{ rel: Relationship, tuple: Tuple }> = []\n for (const id of c.relIds) {\n const rel = state.relationships[id]\n const t = rel && liveRel(rel) ? activeTuple(rel) : undefined\n if (t && !t.deactivated && ids.has(t.entryId)) out.push({ rel, tuple: t })\n }\n return out\n}\n\n/** Where a message to the contact goes now, or why it cannot (5010–5030):\n * the first unblocked, ready channel. */\nexport function messageChannel (state: Readonly<HolderState>, contactId: string): { rel: Relationship, tuple: Tuple } | Refusal {\n const all = channelsOf(state, contactId)\n if (all === null) return no('unknown-contact')\n if (!all.length) return no('no-own-channel', 'RLTP-MSG-5010')\n const open = all.filter((x) => !blockedRel(state, x.rel.id))\n if (!open.length) return no('blocked', 'RLTP-MSG-5030')\n return open.find((x) => tupleReady(state, x.tuple.ownPairLabel)) ?? no('not-ready', 'RLTP-MSG-5020')\n}\n\ninterface SendPrep { draft: OutboundDraft, mid: string, contactId: string }\n\nconst isRefusal = (x: unknown): x is Refusal => (x as Refusal)?.ok === false\n\nconst sendDef: CommandDef<SendInput, SendPrep | Refusal> = {\n human: true,\n async prepare (ctx, input) {\n if (typeof input?.contactId !== 'string' || typeof input.text !== 'string') throw new TypeError('message.send needs {contactId, text}')\n const n = [...input.text].length\n if (n < 1 || n > 4096 || (input.replyTo !== undefined && (typeof input.replyTo !== 'string' || !UUID4.test(input.replyTo)))) return no('message-invalid', 'RLTP-MSG-3020')\n const s = ctx.snapshot\n const ch = messageChannel(s, input.contactId)\n if (isRefusal(ch)) return ch\n const S = ctx.crypto.subtle\n const own = await ctx.keys.anchorOf(ch.tuple.ownPairLabel)\n const raw = xRawOfMk(ch.tuple.counterpartKeyAgreement)\n const a = raw ? await ctx.keys.agree(ch.tuple.rkid, raw, ctx.release) : null\n if (!a || a.status !== 'available') return no('no-own-channel', 'RLTP-MSG-3110')\n const key = await messageKeyOf(a.shared, own.anchor, ch.tuple.counterpartAnchor, S)\n // sentAt in whole seconds (3030), the sender's clock\n const sec = Math.floor(ctx.when / 1000) * 1000\n const body: MessageBody = {\n type: 'message@1', mid: ctx.entropy.id('message.mid'), sentAt: iso(sec), text: input.text,\n ...(input.replyTo !== undefined ? { replyTo: input.replyTo } : {}),\n }\n const payload: MessagePayload = { body, proof: { mac: await messageMac(key, body, S) } }\n const doc = {\n id: ctx.entropy.id('doc.id'), type: MESSAGE_TYPE, issuer: own.anchor, recipient: ch.tuple.counterpartAnchor,\n threadId: ctx.entropy.id('thread.id'), issuedAt: iso(ctx.when), payload,\n }\n const envelope = await seal(doc as never, ch.tuple.counterpartKeyAgreement, { ephSeed: ctx.entropy.bytes('seal.eph', 32), nonce: ctx.entropy.bytes('seal.nonce', 12) }, S)\n const contactId = entryOf(s, ch.rel)?.id ?? ch.rel.contactId\n return {\n mid: body.mid, contactId,\n draft: {\n digest: await digestDoc(doc, S), envelope, type: MESSAGE_TYPE, threadId: doc.threadId,\n recipient: { contactId, rkid: ch.tuple.rkid, keyAgreement: ch.tuple.counterpartKeyAgreement },\n // the sender's give-up a day before the age bound (5110, Delivery 7020)\n expiresAt: sec + MESSAGE_SENDER_LIFETIME_MS,\n },\n }\n },\n apply (state, prepared) {\n const p = prepared.value\n if (isRefusal(p)) return p\n return { state: state as HolderState, outbound: [p.draft], events: [{ type: 'message.sent', contactId: p.contactId, mid: p.mid, digest: p.draft.digest }] }\n },\n}\n\n// ── the message: reception (Section 4) ─────────────────────────────────\n\n/** The inbox entries of the relationship `relId` (through their tuples now). */\nconst inboxCount = (state: Readonly<HolderState>, relId: string): number =>\n Object.values(state.messages.inbox).filter((e) => tupleByLabel(state, e.tuple)?.rel.id === relId).length\n\nconst messageTask: TaskHandler<MessagePayload, { bodyDigest: string }> = {\n proof: 'absent',\n // stage 7: the closed form (4010); the calendar is a verifier's check (3030)\n decode (p) {\n if (!messageShapeOk(p)) return refuse('malformed', 'RLTP-MSG-4010')\n return calOK(p.body.sentAt) ? p : refuse('validation-failed', 'RLTP-MSG-3030')\n },\n async prepare (ctx, doc, arr) {\n const s = ctx.snapshot\n const S = ctx.crypto.subtle\n const at = tupleByRkid(s, arr.rkid)!\n // the MAC under k_msg of the arrival tuple, issuer to recipient (4020, 3110, 3120)\n const raw = xRawOfMk(at.tuple.counterpartKeyAgreement)\n const a = raw ? await ctx.keys.agree(arr.rkid, raw, ctx.release) : null\n if (!a || a.status !== 'available') return refuse('validation-failed', 'RLTP-MSG-4020')\n let key: Uint8Array\n try { key = await messageKeyOf(a.shared, doc.issuer, doc.recipient, S) } catch { return refuse('validation-failed', 'RLTP-MSG-3120') }\n if ((await messageMac(key, doc.payload.body, S)) !== doc.payload.proof.mac) return refuse('validation-failed', 'RLTP-MSG-4020')\n // the bounds (4110), counted before the block (4130): transient (4120)\n const relId = at.rel.id\n if (rateCount(s, relId, 'messages', ctx.when) >= MESSAGE_RATE) return refuse('rate-limited', 'RLTP-MSG-4110')\n // the inbox bound is counted before the block too (4130): a new mid\n // meets the entries held, blocked or not; once it passes, a block\n // discards it, an entry taken over at once\n const known = s.messages.records[at.tuple.ownPairLabel]?.[doc.payload.body.mid] !== undefined\n if (!known && inboxCount(s, relId) >= INBOX_BOUND) return refuse('rate-limited', 'RLTP-MSG-4110')\n return { bodyDigest: await digestDoc(doc.payload.body, S) }\n },\n // stage 9, on t_ref = arr.when (raised to lastWhen, the mark of 4060)\n apply (state, prepared, doc, arr) {\n const at = tupleByRkid(state, arr.rkid)!\n const label = at.tuple.ownPairLabel\n const relId = at.rel.id\n const body = doc.payload.body\n const tRef = arr.when\n const sentAt = Date.parse(body.sentAt)\n if (sentAt + MESSAGE_LIFETIME_MS < tRef) return refuse('stale-issuance', 'RLTP-MSG-4040')\n if (sentAt > tRef + MESSAGE_FUTURE_MS) return refuse('validation-failed', 'RLTP-MSG-4050')\n const { bodyDigest } = prepared.value\n const held = Object.hasOwn(state.messages.records, label) && Object.hasOwn(state.messages.records[label], body.mid) ? state.messages.records[label][body.mid] : undefined\n if (held && held.bodyDigest !== bodyDigest) return refuse('validation-failed', 'RLTP-MSG-4330')\n // the rate counts every new document digest accepted, before the block (4110, 4130)\n let next = withRate(state, relId, 'messages', tRef)\n // a known mid with its body: no new effect, a fresh ack (4320)\n if (held) return { state: next }\n const records = { ...next.messages.records, [label]: { ...(next.messages.records[label] ?? {}), [body.mid]: { bodyDigest, sentAt } } }\n next = { ...next, messages: { ...next.messages, records } }\n // under a block: discard — the record, the cache entry and the ack, nothing else (6210, 6220)\n if (blockedRel(state, relId)) return { state: next }\n const entry: InboxEntry = { id: arr.digest, tuple: label, mid: body.mid, body: body as unknown as JsonObject, receivedAt: tRef, displayAt: Math.min(sentAt, tRef) }\n const contactId = entryOf(state, at.rel)?.id ?? at.rel.contactId\n return {\n state: { ...next, messages: { ...next.messages, inbox: { ...next.messages.inbox, [entry.id]: entry } } },\n events: [{ type: 'message.received', contactId, inboxId: entry.id }],\n }\n },\n}\n\n/** The application took inbox entries over durably (4420). */\nconst takeDef: CommandDef<TakeInput, null> = {\n human: false,\n apply (state, _p, input) {\n if (!Array.isArray(input?.ids) || !input.ids.every((x) => typeof x === 'string')) throw new TypeError('message.take needs {ids: string[]}')\n const gone = input.ids.filter((id) => Object.hasOwn(state.messages.inbox, id))\n if (!gone.length) return { state: state as HolderState }\n const inbox = { ...state.messages.inbox }\n for (const id of gone) delete inbox[id]\n // the completion record stays (4350)\n return { state: { ...state, messages: { ...state.messages, inbox } } }\n },\n}\n\n/** The tuple a counterpart's document was accepted on is ready (5.1). */\nfunction markReady (state: Readonly<HolderState>, doc: ReceivedDocument, arr: Arrival): HolderState {\n const at = tupleByRkid(state, arr.rkid)\n if (!at || doc.issuer !== at.tuple.counterpartAnchor || tupleReady(state, at.tuple.ownPairLabel)) return state as HolderState\n const ready = [...state.messages.ready, at.tuple.ownPairLabel].sort(cmp)\n return { ...state, messages: { ...state.messages, ready } }\n}\n\n/** The completion record's retention (4340): an entry leaves once\n * t_ref (tick's time, written as the mark) lies after sentAt + H, or once\n * its tuple is deactivated or gone; ready marks of tuples gone leave. */\nfunction retainMessages (state: Readonly<HolderState>, when: Millis): HolderState {\n let changed = false\n const records: HolderState['messages']['records'] = {}\n for (const [label, rec] of Object.entries(state.messages.records)) {\n const t = tupleByLabel(state, label)\n if (!t || t.tuple.deactivated) { changed = true; continue }\n const keep = Object.entries(rec).filter(([, e]) => !(e.sentAt + MESSAGE_LIFETIME_MS < when))\n if (keep.length !== Object.keys(rec).length) changed = true\n if (keep.length) records[label] = Object.fromEntries(keep)\n }\n const ready = state.messages.ready.filter((l) => tupleByLabel(state, l) !== null)\n if (ready.length !== state.messages.ready.length) changed = true\n return changed ? { ...state, messages: { ...state.messages, records, ready } } : state as HolderState\n}\n\n/** When retainMessages lets an entry go by time (the timer contract). */\nfunction messageDeadlines (state: Readonly<HolderState>): Millis[] {\n const out: Millis[] = []\n for (const rec of Object.values(state.messages.records)) {\n let first = Infinity\n for (const e of Object.values(rec)) first = Math.min(first, e.sentAt + MESSAGE_LIFETIME_MS + 1)\n if (first !== Infinity) out.push(first)\n }\n return out\n}\n\n// ── the block act (Section 6.1) ────────────────────────────────────────\n\nconst blockDef: CommandDef<BlockInput, null> = {\n human: true,\n apply (state, _p, input) {\n if (typeof input?.contactId !== 'string' || typeof input.blocked !== 'boolean') throw new TypeError('message.block needs {contactId, blocked}')\n const c = findContact(state, input.contactId)\n if (!c) return no('unknown-contact')\n // every relationship of the entry (6020); unblocking deletes nothing\n // else and surfaces nothing (6510)\n const blocked = withBlocked(state.messages.blocked, c.relIds, input.blocked)\n return {\n state: { ...state, messages: { ...state.messages, blocked } },\n events: [{ type: 'contact.blocked', contactId: c.id, blocked: input.blocked }],\n }\n },\n}\n\n/** The message module createHolder registers. */\nexport function messageModule (): HolderModule {\n return Object.freeze({\n name: 'message',\n commands: Object.freeze({ [MESSAGE_COMMANDS.send]: sendDef, [MESSAGE_COMMANDS.block]: blockDef, [MESSAGE_COMMANDS.take]: takeDef }),\n tasks: Object.freeze({ [MESSAGE_TYPE]: messageTask }),\n accepted: markReady,\n retain: retainMessages,\n deadlines: messageDeadlines,\n })\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** The registered type (Message Tasks 3, Delivery 4.4). */
|
|
2
|
+
export declare const MESSAGE_TYPE = "https://real-life.org/trust-tasks/message/0.1";
|
|
3
|
+
/** H, the message lifetime of this version: P180D (Message Tasks 2.2). */
|
|
4
|
+
export declare const MESSAGE_LIFETIME_MS: number;
|
|
5
|
+
/** The future bound of RLTP-MSG-4050: P1D. */
|
|
6
|
+
export declare const MESSAGE_FUTURE_MS = 86400000;
|
|
7
|
+
/** The sender's give-up before H: sentAt + H − P1D (RLTP-MSG-5110, RLTP-DEL-7020). */
|
|
8
|
+
export declare const MESSAGE_SENDER_LIFETIME_MS: number;
|
|
9
|
+
/** At most 500 new message/0.1 document digests per relationship in 24 h (4110). */
|
|
10
|
+
export declare const MESSAGE_RATE = 500;
|
|
11
|
+
/** At most 2000 inbox entries per relationship (4110). */
|
|
12
|
+
export declare const INBOX_BOUND = 2000;
|
|
13
|
+
/** The message@1 body (Message Tasks 3.2). */
|
|
14
|
+
export interface MessageBody {
|
|
15
|
+
type: 'message@1';
|
|
16
|
+
mid: string;
|
|
17
|
+
sentAt: string;
|
|
18
|
+
text: string;
|
|
19
|
+
replyTo?: string;
|
|
20
|
+
}
|
|
21
|
+
/** The payload: `{ body, proof: { mac } }` (3.1). */
|
|
22
|
+
export interface MessagePayload {
|
|
23
|
+
body: MessageBody;
|
|
24
|
+
proof: {
|
|
25
|
+
mac: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/** The HKDF info of k_msg: sender anchor, then recipient anchor (3110). */
|
|
29
|
+
export declare const messageInfo: (senderPairAnchor: string, recipientPairAnchor: string) => string;
|
|
30
|
+
/** k_msg from the tuple's X25519 shared secret (3110); an all-zero
|
|
31
|
+
* secret is rejected before derivation (3120). */
|
|
32
|
+
export declare function messageKeyOf(shared: Uint8Array, senderPairAnchor: string, recipientPairAnchor: string, subtle?: SubtleCrypto): Promise<Uint8Array>;
|
|
33
|
+
/** The MAC of Trust 2.1 over JCS(body): "u" + base64url HMAC-SHA-256. */
|
|
34
|
+
export declare function messageMac(key: Uint8Array, body: unknown, subtle?: SubtleCrypto): Promise<string>;
|
|
35
|
+
/** Whether the payload is a message@1 of the closed form (3010, 3020):
|
|
36
|
+
* the schema, whose maxLength counts code points. */
|
|
37
|
+
export declare const messageShapeOk: (payload: unknown) => payload is MessagePayload;
|
|
38
|
+
/** Why a message@1 fails its form or its MAC under `key`, the vector's
|
|
39
|
+
* names: `schema` (3010, 3020, the pattern of 3030), `calendar` (3030:
|
|
40
|
+
* a date the pattern admits that no calendar has), `mac` (3110); null
|
|
41
|
+
* when it passes. */
|
|
42
|
+
export declare function messageProblem(payload: unknown, key: Uint8Array, subtle?: SubtleCrypto): Promise<'schema' | 'calendar' | 'mac' | null>;
|
|
43
|
+
//# sourceMappingURL=message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../src/message.ts"],"names":[],"mappings":"AAOA,2DAA2D;AAC3D,eAAO,MAAM,YAAY,kDAAkD,CAAA;AAC3E,0EAA0E;AAC1E,eAAO,MAAM,mBAAmB,QAAmB,CAAA;AACnD,8CAA8C;AAC9C,eAAO,MAAM,iBAAiB,WAAa,CAAA;AAC3C,sFAAsF;AACtF,eAAO,MAAM,0BAA0B,QAAmC,CAAA;AAC1E,oFAAoF;AACpF,eAAO,MAAM,YAAY,MAAM,CAAA;AAC/B,0DAA0D;AAC1D,eAAO,MAAM,WAAW,OAAO,CAAA;AAE/B,8CAA8C;AAC9C,MAAM,WAAW,WAAW;IAAG,IAAI,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;AAC/G,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAAG,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE;AAM7E,2EAA2E;AAC3E,eAAO,MAAM,WAAW,GAAI,kBAAkB,MAAM,EAAE,qBAAqB,MAAM,KAAG,MACb,CAAA;AAEvE;mDACmD;AACnD,wBAAsB,YAAY,CAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAGzJ;AAED,yEAAyE;AACzE,wBAAsB,UAAU,CAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAIxG;AAED;sDACsD;AACtD,eAAO,MAAM,cAAc,GAAI,SAAS,OAAO,KAAG,OAAO,IAAI,cAAkE,CAAA;AAE/H;;;sBAGsB;AACtB,wBAAsB,cAAc,CAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,GAAG,UAAU,GAAG,KAAK,GAAG,IAAI,CAAC,CAI7I"}
|
package/dist/message.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// message — the pure forms and checks of Message Tasks 0.1 (§3): the
|
|
2
|
+
// message@1 body, the directional key k_msg and its MAC, used by the
|
|
3
|
+
// holder's message module (message/holder.ts). State-free.
|
|
4
|
+
import { b64uOf, calOK, jcs, makeValidator } from './core.js';
|
|
5
|
+
import { hkdf, platformSubtle } from './crypto.js';
|
|
6
|
+
import { SCHEMAS } from './schemas.js';
|
|
7
|
+
/** The registered type (Message Tasks 3, Delivery 4.4). */
|
|
8
|
+
export const MESSAGE_TYPE = 'https://real-life.org/trust-tasks/message/0.1';
|
|
9
|
+
/** H, the message lifetime of this version: P180D (Message Tasks 2.2). */
|
|
10
|
+
export const MESSAGE_LIFETIME_MS = 180 * 86_400_000;
|
|
11
|
+
/** The future bound of RLTP-MSG-4050: P1D. */
|
|
12
|
+
export const MESSAGE_FUTURE_MS = 86_400_000;
|
|
13
|
+
/** The sender's give-up before H: sentAt + H − P1D (RLTP-MSG-5110, RLTP-DEL-7020). */
|
|
14
|
+
export const MESSAGE_SENDER_LIFETIME_MS = MESSAGE_LIFETIME_MS - 86_400_000;
|
|
15
|
+
/** At most 500 new message/0.1 document digests per relationship in 24 h (4110). */
|
|
16
|
+
export const MESSAGE_RATE = 500;
|
|
17
|
+
/** At most 2000 inbox entries per relationship (4110). */
|
|
18
|
+
export const INBOX_BOUND = 2000;
|
|
19
|
+
const te = new TextEncoder();
|
|
20
|
+
const V = makeValidator(SCHEMAS);
|
|
21
|
+
const SCHEMA = SCHEMAS['message.schema.json'];
|
|
22
|
+
/** The HKDF info of k_msg: sender anchor, then recipient anchor (3110). */
|
|
23
|
+
export const messageInfo = (senderPairAnchor, recipientPairAnchor) => 'rltp/v1/message/mac/' + senderPairAnchor + '/' + recipientPairAnchor;
|
|
24
|
+
/** k_msg from the tuple's X25519 shared secret (3110); an all-zero
|
|
25
|
+
* secret is rejected before derivation (3120). */
|
|
26
|
+
export async function messageKeyOf(shared, senderPairAnchor, recipientPairAnchor, subtle) {
|
|
27
|
+
if (shared.every((b) => b === 0))
|
|
28
|
+
throw new Error('all-zero X25519 output (RLTP-MSG-3120)');
|
|
29
|
+
return hkdf(shared, messageInfo(senderPairAnchor, recipientPairAnchor), 32, subtle ?? platformSubtle());
|
|
30
|
+
}
|
|
31
|
+
/** The MAC of Trust 2.1 over JCS(body): "u" + base64url HMAC-SHA-256. */
|
|
32
|
+
export async function messageMac(key, body, subtle) {
|
|
33
|
+
const S = subtle ?? platformSubtle();
|
|
34
|
+
const k = await S.importKey('raw', key, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
|
|
35
|
+
return 'u' + b64uOf(new Uint8Array(await S.sign('HMAC', k, te.encode(jcs(body)))));
|
|
36
|
+
}
|
|
37
|
+
/** Whether the payload is a message@1 of the closed form (3010, 3020):
|
|
38
|
+
* the schema, whose maxLength counts code points. */
|
|
39
|
+
export const messageShapeOk = (payload) => V.validate(payload, SCHEMA, SCHEMA).length === 0;
|
|
40
|
+
/** Why a message@1 fails its form or its MAC under `key`, the vector's
|
|
41
|
+
* names: `schema` (3010, 3020, the pattern of 3030), `calendar` (3030:
|
|
42
|
+
* a date the pattern admits that no calendar has), `mac` (3110); null
|
|
43
|
+
* when it passes. */
|
|
44
|
+
export async function messageProblem(payload, key, subtle) {
|
|
45
|
+
if (!messageShapeOk(payload))
|
|
46
|
+
return 'schema';
|
|
47
|
+
if (!calOK(payload.body.sentAt))
|
|
48
|
+
return 'calendar';
|
|
49
|
+
return (await messageMac(key, payload.body, subtle)) === payload.proof.mac ? null : 'mac';
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../src/message.ts"],"names":[],"mappings":"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","sourcesContent":["// message — the pure forms and checks of Message Tasks 0.1 (§3): the\n// message@1 body, the directional key k_msg and its MAC, used by the\n// holder's message module (message/holder.ts). State-free.\nimport { b64uOf, calOK, jcs, makeValidator } from './core.js'\nimport { hkdf, platformSubtle } from './crypto.js'\nimport { SCHEMAS } from './schemas.js'\n\n/** The registered type (Message Tasks 3, Delivery 4.4). */\nexport const MESSAGE_TYPE = 'https://real-life.org/trust-tasks/message/0.1'\n/** H, the message lifetime of this version: P180D (Message Tasks 2.2). */\nexport const MESSAGE_LIFETIME_MS = 180 * 86_400_000\n/** The future bound of RLTP-MSG-4050: P1D. */\nexport const MESSAGE_FUTURE_MS = 86_400_000\n/** The sender's give-up before H: sentAt + H − P1D (RLTP-MSG-5110, RLTP-DEL-7020). */\nexport const MESSAGE_SENDER_LIFETIME_MS = MESSAGE_LIFETIME_MS - 86_400_000\n/** At most 500 new message/0.1 document digests per relationship in 24 h (4110). */\nexport const MESSAGE_RATE = 500\n/** At most 2000 inbox entries per relationship (4110). */\nexport const INBOX_BOUND = 2000\n\n/** The message@1 body (Message Tasks 3.2). */\nexport interface MessageBody { type: 'message@1', mid: string, sentAt: string, text: string, replyTo?: string }\n/** The payload: `{ body, proof: { mac } }` (3.1). */\nexport interface MessagePayload { body: MessageBody, proof: { mac: string } }\n\nconst te = new TextEncoder()\nconst V = makeValidator(SCHEMAS)\nconst SCHEMA = SCHEMAS['message.schema.json']\n\n/** The HKDF info of k_msg: sender anchor, then recipient anchor (3110). */\nexport const messageInfo = (senderPairAnchor: string, recipientPairAnchor: string): string =>\n 'rltp/v1/message/mac/' + senderPairAnchor + '/' + recipientPairAnchor\n\n/** k_msg from the tuple's X25519 shared secret (3110); an all-zero\n * secret is rejected before derivation (3120). */\nexport async function messageKeyOf (shared: Uint8Array, senderPairAnchor: string, recipientPairAnchor: string, subtle?: SubtleCrypto): Promise<Uint8Array> {\n if (shared.every((b) => b === 0)) throw new Error('all-zero X25519 output (RLTP-MSG-3120)')\n return hkdf(shared, messageInfo(senderPairAnchor, recipientPairAnchor), 32, subtle ?? platformSubtle())\n}\n\n/** The MAC of Trust 2.1 over JCS(body): \"u\" + base64url HMAC-SHA-256. */\nexport async function messageMac (key: Uint8Array, body: unknown, subtle?: SubtleCrypto): Promise<string> {\n const S = subtle ?? platformSubtle()\n const k = await S.importKey('raw', key, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'])\n return 'u' + b64uOf(new Uint8Array(await S.sign('HMAC', k, te.encode(jcs(body)))))\n}\n\n/** Whether the payload is a message@1 of the closed form (3010, 3020):\n * the schema, whose maxLength counts code points. */\nexport const messageShapeOk = (payload: unknown): payload is MessagePayload => V.validate(payload, SCHEMA, SCHEMA).length === 0\n\n/** Why a message@1 fails its form or its MAC under `key`, the vector's\n * names: `schema` (3010, 3020, the pattern of 3030), `calendar` (3030:\n * a date the pattern admits that no calendar has), `mac` (3110); null\n * when it passes. */\nexport async function messageProblem (payload: unknown, key: Uint8Array, subtle?: SubtleCrypto): Promise<'schema' | 'calendar' | 'mac' | null> {\n if (!messageShapeOk(payload)) return 'schema'\n if (!calOK(payload.body.sentAt)) return 'calendar'\n return (await messageMac(key, payload.body, subtle)) === payload.proof.mac ? null : 'mac'\n}\n"]}
|