@real-life/trust-protocol 0.1.1 → 0.2.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/README.md +14 -10
- package/dist/carrier-identity.d.ts +9 -0
- package/dist/carrier-identity.d.ts.map +1 -1
- package/dist/carrier-identity.js +32 -2
- package/dist/carrier-identity.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/probe/acks.d.ts +27 -0
- package/dist/probe/acks.d.ts.map +1 -0
- package/dist/probe/acks.js +119 -0
- package/dist/probe/acks.js.map +1 -0
- package/dist/probe/continuity.d.ts +3 -82
- package/dist/probe/continuity.d.ts.map +1 -1
- package/dist/probe/continuity.js +627 -147
- package/dist/probe/continuity.js.map +1 -1
- package/dist/probe/trust.d.ts +114 -74
- package/dist/probe/trust.d.ts.map +1 -1
- package/dist/probe/trust.js +1090 -232
- package/dist/probe/trust.js.map +1 -1
- package/dist/probe.d.ts +0 -2
- package/dist/probe.d.ts.map +1 -1
- package/dist/probe.js +5 -7
- package/dist/probe.js.map +1 -1
- package/dist/schemas.js +22 -22
- package/dist/schemas.js.map +1 -1
- package/dist/visibility.d.ts +6 -0
- package/dist/visibility.d.ts.map +1 -0
- package/dist/visibility.js +30 -0
- package/dist/visibility.js.map +1 -0
- package/dist/wire.d.ts +28 -26
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -35,6 +35,7 @@ look in the code:
|
|
|
35
35
|
| `carrier-identity` | Identity §7a | The carrier-relationship principal: one Ed25519 control key per (relationship × carrier), derived so that no computable relation to the relationship's other principals or its `rkid` exists — which is why registration must *prove* the binding instead of computing it. |
|
|
36
36
|
| `carrier` | Delivery §4.4 + §5a | The carrier side of the port as one transport-agnostic state machine: the five guarantees, the proof rule, the total binding lifecycle (unbound → live → closing → released), the verdict sets in their normative evaluation orders, wind-up and binding tombstones. The clock is injected. |
|
|
37
37
|
| `holder` | Delivery §5a + Identity §9.3 | The holder's half: proof construction for all four purposes, the closed verdict set, and the two-exchange recovery flow for a lost carrier entry. |
|
|
38
|
+
| `visibility` | Network Visibility 0.29 on Delivery 0.79 | The trust act (`anchor-mapping@2` + `grade-declaration@1`), the blinded star (`star@1`, 5.2a chunks), the admission layer and the 5.4 reconciliation automaton, §6a continuity (probe + mapping — chains instead of duplicates), and the deniable `delivery-ack/0.1`. Namespaced: `visibility.trust`, `.continuity`, `.acks`. Graduated from `/probe` on 04.09.2026 after a 39-round conformance loop. |
|
|
38
39
|
|
|
39
40
|
Everything is re-exported from the package root; the table is a map, not an
|
|
40
41
|
import instruction.
|
|
@@ -46,17 +47,19 @@ import { labeledContext, signCard, seal, sameDigest } from '@real-life/trust-pro
|
|
|
46
47
|
## Two entry points
|
|
47
48
|
|
|
48
49
|
```ts
|
|
49
|
-
import {
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
import { …, visibility } from '@real-life/trust-protocol' // wire-normative core
|
|
51
|
+
const { trust, continuity, acks } = visibility // Network Visibility, graduated
|
|
52
|
+
import { introduce, membership }
|
|
53
|
+
from '@real-life/trust-protocol/probe' // draft — will change
|
|
52
54
|
```
|
|
53
55
|
|
|
54
56
|
The **`/probe` subpath is deliberate.** Its modules exercise the converged
|
|
55
57
|
*semantics* of their layers, but their transport shapes carry `@probe` and
|
|
56
|
-
are **not wire-normative**: mediated introductions over a rendezvous drop
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
are **not wire-normative**: mediated introductions over a rendezvous drop
|
|
59
|
+
and group membership (founding, VIC invite, admission, vouching). The
|
|
60
|
+
trust act, the blinded star, §6a continuity and the deniable ack **left
|
|
61
|
+
this subpath on 04.09.2026** — they are wire-normative now and live under
|
|
62
|
+
`visibility` at the package root. Experiment with the rest; do not treat its wire forms
|
|
60
63
|
as an interoperability target. A subpath import is a decision someone has
|
|
61
64
|
to make — nothing behind it can be reached by accident.
|
|
62
65
|
|
|
@@ -75,15 +78,16 @@ This package uses its own semver; the specification uses castings. Each
|
|
|
75
78
|
release states, per module, whose **wire forms** it implements — and what
|
|
76
79
|
it deliberately does not:
|
|
77
80
|
|
|
78
|
-
| Module (0.
|
|
81
|
+
| Module (0.2.x) | Casting | Implemented | Not in this package |
|
|
79
82
|
|---|---|---|---|
|
|
80
83
|
| `identity` | Identity 0.50 | context derivation under the closed label registry (§6.1, unchanged since 0.13) with the ordered persona pipeline (§6.2, Unicode 15.0 pinned) | recovery derivation (§5.3), service identities (§7), the label register and its state |
|
|
81
84
|
| `carrier-identity` | Identity 0.51 (§7a) | the carrier-relationship principal derivation, identifier validation | the register's generation state (held by the holder's store) |
|
|
82
|
-
| `carrier` + `holder` | Delivery 0.
|
|
85
|
+
| `carrier` + `holder` | Delivery 0.79 (§4.4, §5a) + Identity 0.51 (§9.3) | the port state machine, proofs for all four purposes, verdicts, recovery | transport adapters and their policies (a carrier's budgets enter through hooks) |
|
|
83
86
|
| `encounter` | Encounter 0.29 — wire `0.25` (`rltp-card/0.25`, `encounter-scan@0.25`) | challenges, both card profiles, the enactment binding, encounter credentials | the ceremony state machine, acceptance rules, ack deadlines |
|
|
84
87
|
| `delivery` | Delivery 0.64 | the sealed envelope (§5) and the generic receive stages 1–4 | the type-specific stages, residual bookkeeping, transport adapters |
|
|
85
88
|
| `core`, `crypto` | cross-layer | canonical form, digest equality, timestamps, validator; primitives + `eddsa-jcs-2022` proof | — |
|
|
86
|
-
|
|
|
89
|
+
| `visibility` | Network Visibility 0.29 + Delivery 0.79 (§3, §4.2, §4.4) | the trust act (`anchor-mapping@2`, `grade-declaration@1`), `star@1` with 5.2a chunk assembly, the admission layer (Section 2), the 5.4 reconciliation automaton with completion via deniable acks, §6a continuity (`continuity-probe@1`, `continuity-mapping@1`, chaining), the registered task documents and `delivery-ack/0.1` with the 4.2 class rule; full §6.2 stage order on every receive path, peek→build→commit issuance on every producer | storage, transport adapters and their policies, the Encounter layer's ceremony flows (still `@probe`) |
|
|
90
|
+
| `/probe` | Network Visibility (introductions) · Membership Tasks + Access | mediated introductions, group membership — semantics of the running castings, transport shapes `@probe` | any wire-form stability whatsoever |
|
|
87
91
|
|
|
88
92
|
Persona-name validation is **pinned to Unicode 15.0** as Identity §6.2
|
|
89
93
|
requires: the repertoire ships with the package (`unicode15.ts`, ~5 kB of
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { KeyPair } from './crypto.js';
|
|
2
2
|
export declare const CARRIER_INFO_PREFIX = "rltp/v1/carrier-relationship/ed25519/v1/";
|
|
3
|
+
export declare const CONNECTION_INFO_PREFIX = "rltp/v1/carrier-connection/ed25519/v1/";
|
|
4
|
+
export declare const EGRESS_INFO_PREFIX = "rltp/v1/carrier-egress/ed25519/v1/";
|
|
3
5
|
export declare function validCarrierIdentifier(c: unknown): c is string;
|
|
4
6
|
export interface CarrierPrincipal {
|
|
5
7
|
principal: string;
|
|
@@ -8,4 +10,11 @@ export interface CarrierPrincipal {
|
|
|
8
10
|
keyAgreement: null;
|
|
9
11
|
}
|
|
10
12
|
export declare function carrierPrincipal(rootIkm: Uint8Array, carrier: string, nonce: Uint8Array): Promise<CarrierPrincipal>;
|
|
13
|
+
export interface CarrierScopedIdentity {
|
|
14
|
+
did: string;
|
|
15
|
+
key: KeyPair;
|
|
16
|
+
info: string;
|
|
17
|
+
scope: 'connection' | 'egress';
|
|
18
|
+
}
|
|
19
|
+
export declare function carrierScopedIdentity(rootIkm: Uint8Array, carrier: string, nonce: Uint8Array, scope: 'connection' | 'egress'): Promise<CarrierScopedIdentity>;
|
|
11
20
|
//# sourceMappingURL=carrier-identity.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carrier-identity.d.ts","sourceRoot":"","sources":["../src/carrier-identity.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAK1C,eAAO,MAAM,mBAAmB,6CAA6C,CAAA;
|
|
1
|
+
{"version":3,"file":"carrier-identity.d.ts","sourceRoot":"","sources":["../src/carrier-identity.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAK1C,eAAO,MAAM,mBAAmB,6CAA6C,CAAA;AAS7E,eAAO,MAAM,sBAAsB,2CAA2C,CAAA;AAC9E,eAAO,MAAM,kBAAkB,uCAAuC,CAAA;AA4BtE,wBAAgB,sBAAsB,CAAE,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,MAAM,CAmB/D;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,OAAO,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,IAAI,CAAA;CACnB;AAKD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GACtD,OAAO,CAAC,gBAAgB,CAAC,CAY3B;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,OAAO,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,YAAY,GAAG,QAAQ,CAAA;CAC/B;AAKD,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EACvD,KAAK,EAAE,YAAY,GAAG,QAAQ,GAC7B,OAAO,CAAC,qBAAqB,CAAC,CAUhC"}
|
package/dist/carrier-identity.js
CHANGED
|
@@ -20,6 +20,15 @@ import { sha, hkdf, edFromSeed, anchorOfEd } from './crypto.js';
|
|
|
20
20
|
import { WHITE_SPACE_15 } from './unicode15.js';
|
|
21
21
|
const te = new TextEncoder();
|
|
22
22
|
export const CARRIER_INFO_PREFIX = 'rltp/v1/carrier-relationship/ed25519/v1/';
|
|
23
|
+
// Adapter-scoped identities (profile spec/adapter-vti-mediator.md,
|
|
24
|
+
// Delivery §5a.10): the mediation connection DID and the sender-side
|
|
25
|
+
// egress identity. Both derive from the same root as the control
|
|
26
|
+
// principal but under distinct info prefixes — each is derivable from
|
|
27
|
+
// the root, none from any other. That is exactly the §5a.10 sentence
|
|
28
|
+
// "never a control principal or derivable from one", satisfied by
|
|
29
|
+
// construction: without rootIkm no party can compute one from another.
|
|
30
|
+
export const CONNECTION_INFO_PREFIX = 'rltp/v1/carrier-connection/ed25519/v1/';
|
|
31
|
+
export const EGRESS_INFO_PREFIX = 'rltp/v1/carrier-egress/ed25519/v1/';
|
|
23
32
|
// multihash(sha2-256) in base64url — the digest form Identity §7a.4 fixes
|
|
24
33
|
const mh = async (bytes) => 'u' + b64uOf(cat(Uint8Array.from([0x12, 0x20]), await sha(bytes)));
|
|
25
34
|
// Identity §7a.2 — the ordered validation pipeline for C, fail closed
|
|
@@ -77,9 +86,30 @@ export async function carrierPrincipal(rootIkm, carrier, nonce) {
|
|
|
77
86
|
throw new Error('invalid carrier identifier (7a.2)');
|
|
78
87
|
if (nonce.length !== 32)
|
|
79
88
|
throw new Error('carrier nonce must be 32 bytes (7a.3)');
|
|
80
|
-
|
|
81
|
-
|
|
89
|
+
// M-3: the derivation reads its inputs at entry, once. Caller-held
|
|
90
|
+
// buffers can be mutated while the HKDF awaits; copies make the
|
|
91
|
+
// derived principal a function of the arguments as passed.
|
|
92
|
+
const ikm = rootIkm.slice();
|
|
93
|
+
const n = nonce.slice();
|
|
94
|
+
const info = CARRIER_INFO_PREFIX + await mh(te.encode(carrier)) + await mh(n);
|
|
95
|
+
const seed = await hkdf(ikm, info);
|
|
82
96
|
const key = await edFromSeed(seed);
|
|
83
97
|
return { principal: anchorOfEd(key.pubRaw), key, info, keyAgreement: null };
|
|
84
98
|
}
|
|
99
|
+
// One connection DID / one egress identity per (relationship × carrier),
|
|
100
|
+
// same derivation discipline and same input rules as the principal
|
|
101
|
+
// (§7a.4), distinct prefix. Retired with the principal, never reused.
|
|
102
|
+
export async function carrierScopedIdentity(rootIkm, carrier, nonce, scope) {
|
|
103
|
+
if (!validCarrierIdentifier(carrier))
|
|
104
|
+
throw new Error('invalid carrier identifier (7a.2)');
|
|
105
|
+
if (nonce.length !== 32)
|
|
106
|
+
throw new Error('carrier nonce must be 32 bytes (7a.3)');
|
|
107
|
+
const ikm = rootIkm.slice();
|
|
108
|
+
const n = nonce.slice();
|
|
109
|
+
const prefix = scope === 'connection' ? CONNECTION_INFO_PREFIX : EGRESS_INFO_PREFIX;
|
|
110
|
+
const info = prefix + await mh(te.encode(carrier)) + await mh(n);
|
|
111
|
+
const seed = await hkdf(ikm, info);
|
|
112
|
+
const key = await edFromSeed(seed);
|
|
113
|
+
return { did: anchorOfEd(key.pubRaw), key, info, scope };
|
|
114
|
+
}
|
|
85
115
|
//# sourceMappingURL=carrier-identity.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carrier-identity.js","sourceRoot":"","sources":["../src/carrier-identity.ts"],"names":[],"mappings":"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","sourcesContent":["// carrier-identity — Identity §7a: the carrier-relationship identity class.\n//\n// One control principal per (relationship × carrier), Ed25519-only. The\n// derivation shares no computable relation with the relationship's other\n// principals or with its `rkid` — that absence is the privacy property\n// the whole class exists for (§7a.5), and it is why registration must\n// PROVE the binding instead of computing it (Delivery §5a.3).\n//\n// info = \"rltp/v1/carrier-relationship/ed25519/v1/\" || Dc || Dn\n// where Dc = multihash(sha2-256, UTF-8 of the configured carrier\n// identifier C) and Dn = multihash(sha2-256, 32-byte carrier nonce N),\n// each rendered as 'u' + base64url — exactly 47 characters, so the two\n// parts are length-fixed and no concatenation ambiguity exists (§7a.4).\n//\n// NO key-agreement key is derived for this class: sealing stays at the\n// `rkid` (§7a.1), and a carrier that never holds a decryption key can\n// never be asked to use one.\nimport { b64uOf, cat } from './crypto.js'\nimport { sha, hkdf, edFromSeed, anchorOfEd } from './crypto.js'\nimport type { KeyPair } from './crypto.js'\nimport { WHITE_SPACE_15 } from './unicode15.js'\n\nconst te = new TextEncoder()\n\nexport const CARRIER_INFO_PREFIX = 'rltp/v1/carrier-relationship/ed25519/v1/'\n\n// multihash(sha2-256) in base64url — the digest form Identity §7a.4 fixes\nconst mh = async (bytes: Uint8Array): Promise<string> =>\n 'u' + b64uOf(cat(Uint8Array.from([0x12, 0x20]), await sha(bytes)))\n\n// Identity §7a.2 — the ordered validation pipeline for C, fail closed\n// and NO normalization (the deliberate difference to §6.2): valid\n// Unicode scalar values only (unpaired surrogates never repaired),\n// 1..1024 UTF-8 BYTES, and no Cc, Cf or White_Space code point anywhere.\n//\n// The category tables are PINNED to Unicode 15.0 (port-review-2 M-6):\n// evaluating against the platform's \\p{...} data would let the same\n// identifier derive a principal on one runtime and be rejected on\n// another the moment a Unicode revision moves a code point — the exact\n// defect the persona repertoire (unicode15.ts) already closed for §6.2.\n// Cc is the stable C0/C1 block; Cf is the 170-code-point Unicode-15.0\n// set, enumerated below; White_Space is unicode15.ts's pinned set.\nconst CC_15 = (cp: number): boolean => cp <= 0x1f || (cp >= 0x7f && cp <= 0x9f)\nconst CF_15_RANGES: Array<[number, number]> = [\n [0x00ad, 0x00ad], [0x0600, 0x0605], [0x061c, 0x061c], [0x06dd, 0x06dd],\n [0x070f, 0x070f], [0x0890, 0x0891], [0x08e2, 0x08e2], [0x180e, 0x180e],\n [0x200b, 0x200f], [0x202a, 0x202e], [0x2060, 0x2064], [0x2066, 0x206f],\n [0xfeff, 0xfeff], [0xfff9, 0xfffb], [0x110bd, 0x110bd], [0x110cd, 0x110cd],\n [0x13430, 0x1343f], [0x1bca0, 0x1bca3], [0x1d173, 0x1d17a],\n [0xe0001, 0xe0001], [0xe0020, 0xe007f],\n]\nconst CF_15 = (cp: number): boolean => CF_15_RANGES.some(([a, b]) => cp >= a && cp <= b)\nexport function validCarrierIdentifier (c: unknown): c is string {\n if (typeof c !== 'string' || c.length === 0) return false\n // scalar values: an unpaired surrogate is not a Unicode string\n for (let i = 0; i < c.length; i++) {\n const u = c.charCodeAt(i)\n if (u >= 0xdc00 && u <= 0xdfff) return false // lone low\n if (u >= 0xd800 && u <= 0xdbff) {\n const nxt = c.charCodeAt(i + 1)\n if (!(nxt >= 0xdc00 && nxt <= 0xdfff)) return false // lone high\n i++\n }\n }\n const bytes = new TextEncoder().encode(c)\n if (bytes.length < 1 || bytes.length > 1024) return false\n for (const ch of c) {\n const cp = ch.codePointAt(0)!\n if (CC_15(cp) || CF_15(cp) || WHITE_SPACE_15.has(cp)) return false\n }\n return true\n}\n\nexport interface CarrierPrincipal {\n principal: string // did:key:z6Mk…, the control principal\n key: KeyPair // its Ed25519 pair (for the proofs of §5a.3)\n info: string // the derivation info, for auditability\n keyAgreement: null // declared, not omitted: Ed25519-only (§7a.1)\n}\n\n// Identity §7a.4 — derive the control principal for one relationship at\n// one carrier. `carrier` is C exactly as configured (byte-exact), `nonce`\n// is the relationship's 32-byte carrier nonce N from the register (§7a.3).\nexport async function carrierPrincipal (\n rootIkm: Uint8Array, carrier: string, nonce: Uint8Array,\n): Promise<CarrierPrincipal> {\n if (!validCarrierIdentifier(carrier)) throw new Error('invalid carrier identifier (7a.2)')\n if (nonce.length !== 32) throw new Error('carrier nonce must be 32 bytes (7a.3)')\n const info = CARRIER_INFO_PREFIX + await mh(te.encode(carrier)) + await mh(nonce)\n const seed = await hkdf(rootIkm, info)\n const key = await edFromSeed(seed)\n return { principal: anchorOfEd(key.pubRaw), key, info, keyAgreement: null }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"carrier-identity.js","sourceRoot":"","sources":["../src/carrier-identity.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,EAAE;AACF,wEAAwE;AACxE,yEAAyE;AACzE,uEAAuE;AACvE,sEAAsE;AACtE,8DAA8D;AAC9D,EAAE;AACF,gEAAgE;AAChE,iEAAiE;AACjE,uEAAuE;AACvE,uEAAuE;AACvE,wEAAwE;AACxE,EAAE;AACF,uEAAuE;AACvE,sEAAsE;AACtE,6BAA6B;AAC7B,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE/D,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE/C,MAAM,EAAE,GAAG,IAAI,WAAW,EAAE,CAAA;AAE5B,MAAM,CAAC,MAAM,mBAAmB,GAAG,0CAA0C,CAAA;AAE7E,mEAAmE;AACnE,qEAAqE;AACrE,iEAAiE;AACjE,sEAAsE;AACtE,qEAAqE;AACrE,kEAAkE;AAClE,uEAAuE;AACvE,MAAM,CAAC,MAAM,sBAAsB,GAAG,wCAAwC,CAAA;AAC9E,MAAM,CAAC,MAAM,kBAAkB,GAAG,oCAAoC,CAAA;AAEtE,0EAA0E;AAC1E,MAAM,EAAE,GAAG,KAAK,EAAE,KAAiB,EAAmB,EAAE,CACtD,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AAEpE,sEAAsE;AACtE,kEAAkE;AAClE,mEAAmE;AACnE,yEAAyE;AACzE,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,kEAAkE;AAClE,uEAAuE;AACvE,wEAAwE;AACxE,sEAAsE;AACtE,mEAAmE;AACnE,MAAM,KAAK,GAAG,CAAC,EAAU,EAAW,EAAE,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,IAAI,EAAE,IAAI,IAAI,CAAC,CAAA;AAC/E,MAAM,YAAY,GAA4B;IAC5C,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;IACtE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;IACtE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;IACtE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1E,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1D,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC;CACvC,CAAA;AACD,MAAM,KAAK,GAAG,CAAC,EAAU,EAAW,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;AACxF,MAAM,UAAU,sBAAsB,CAAE,CAAU;IAChD,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACzD,+DAA+D;IAC/D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;QACzB,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM;YAAE,OAAO,KAAK,CAAA,CAAuB,WAAW;QAC9E,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YAC/B,IAAI,CAAC,CAAC,GAAG,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,CAAC;gBAAE,OAAO,KAAK,CAAA,CAAc,YAAY;YAC7E,CAAC,EAAE,CAAA;QACL,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IACzC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI;QAAE,OAAO,KAAK,CAAA;IACzD,KAAK,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;QACnB,MAAM,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAE,CAAA;QAC7B,IAAI,KAAK,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO,KAAK,CAAA;IACpE,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AASD,wEAAwE;AACxE,0EAA0E;AAC1E,2EAA2E;AAC3E,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAmB,EAAE,OAAe,EAAE,KAAiB;IAEvD,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAA;IAC1F,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAA;IACjF,mEAAmE;IACnE,gEAAgE;IAChE,2DAA2D;IAC3D,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,EAAE,CAAA;IAC3B,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,CAAA;IACvB,MAAM,IAAI,GAAG,mBAAmB,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,CAAA;IAC7E,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAClC,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,CAAA;IAClC,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAA;AAC7E,CAAC;AASD,yEAAyE;AACzE,mEAAmE;AACnE,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAmB,EAAE,OAAe,EAAE,KAAiB,EACvD,KAA8B;IAE9B,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAA;IAC1F,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAA;IACjF,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,EAAE,CAAA;IAC3B,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,CAAA;IACvB,MAAM,MAAM,GAAG,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,kBAAkB,CAAA;IACnF,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,CAAA;IAChE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAClC,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,CAAA;IAClC,OAAO,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;AAC1D,CAAC","sourcesContent":["// carrier-identity — Identity §7a: the carrier-relationship identity class.\n//\n// One control principal per (relationship × carrier), Ed25519-only. The\n// derivation shares no computable relation with the relationship's other\n// principals or with its `rkid` — that absence is the privacy property\n// the whole class exists for (§7a.5), and it is why registration must\n// PROVE the binding instead of computing it (Delivery §5a.3).\n//\n// info = \"rltp/v1/carrier-relationship/ed25519/v1/\" || Dc || Dn\n// where Dc = multihash(sha2-256, UTF-8 of the configured carrier\n// identifier C) and Dn = multihash(sha2-256, 32-byte carrier nonce N),\n// each rendered as 'u' + base64url — exactly 47 characters, so the two\n// parts are length-fixed and no concatenation ambiguity exists (§7a.4).\n//\n// NO key-agreement key is derived for this class: sealing stays at the\n// `rkid` (§7a.1), and a carrier that never holds a decryption key can\n// never be asked to use one.\nimport { b64uOf, cat } from './crypto.js'\nimport { sha, hkdf, edFromSeed, anchorOfEd } from './crypto.js'\nimport type { KeyPair } from './crypto.js'\nimport { WHITE_SPACE_15 } from './unicode15.js'\n\nconst te = new TextEncoder()\n\nexport const CARRIER_INFO_PREFIX = 'rltp/v1/carrier-relationship/ed25519/v1/'\n\n// Adapter-scoped identities (profile spec/adapter-vti-mediator.md,\n// Delivery §5a.10): the mediation connection DID and the sender-side\n// egress identity. Both derive from the same root as the control\n// principal but under distinct info prefixes — each is derivable from\n// the root, none from any other. That is exactly the §5a.10 sentence\n// \"never a control principal or derivable from one\", satisfied by\n// construction: without rootIkm no party can compute one from another.\nexport const CONNECTION_INFO_PREFIX = 'rltp/v1/carrier-connection/ed25519/v1/'\nexport const EGRESS_INFO_PREFIX = 'rltp/v1/carrier-egress/ed25519/v1/'\n\n// multihash(sha2-256) in base64url — the digest form Identity §7a.4 fixes\nconst mh = async (bytes: Uint8Array): Promise<string> =>\n 'u' + b64uOf(cat(Uint8Array.from([0x12, 0x20]), await sha(bytes)))\n\n// Identity §7a.2 — the ordered validation pipeline for C, fail closed\n// and NO normalization (the deliberate difference to §6.2): valid\n// Unicode scalar values only (unpaired surrogates never repaired),\n// 1..1024 UTF-8 BYTES, and no Cc, Cf or White_Space code point anywhere.\n//\n// The category tables are PINNED to Unicode 15.0 (port-review-2 M-6):\n// evaluating against the platform's \\p{...} data would let the same\n// identifier derive a principal on one runtime and be rejected on\n// another the moment a Unicode revision moves a code point — the exact\n// defect the persona repertoire (unicode15.ts) already closed for §6.2.\n// Cc is the stable C0/C1 block; Cf is the 170-code-point Unicode-15.0\n// set, enumerated below; White_Space is unicode15.ts's pinned set.\nconst CC_15 = (cp: number): boolean => cp <= 0x1f || (cp >= 0x7f && cp <= 0x9f)\nconst CF_15_RANGES: Array<[number, number]> = [\n [0x00ad, 0x00ad], [0x0600, 0x0605], [0x061c, 0x061c], [0x06dd, 0x06dd],\n [0x070f, 0x070f], [0x0890, 0x0891], [0x08e2, 0x08e2], [0x180e, 0x180e],\n [0x200b, 0x200f], [0x202a, 0x202e], [0x2060, 0x2064], [0x2066, 0x206f],\n [0xfeff, 0xfeff], [0xfff9, 0xfffb], [0x110bd, 0x110bd], [0x110cd, 0x110cd],\n [0x13430, 0x1343f], [0x1bca0, 0x1bca3], [0x1d173, 0x1d17a],\n [0xe0001, 0xe0001], [0xe0020, 0xe007f],\n]\nconst CF_15 = (cp: number): boolean => CF_15_RANGES.some(([a, b]) => cp >= a && cp <= b)\nexport function validCarrierIdentifier (c: unknown): c is string {\n if (typeof c !== 'string' || c.length === 0) return false\n // scalar values: an unpaired surrogate is not a Unicode string\n for (let i = 0; i < c.length; i++) {\n const u = c.charCodeAt(i)\n if (u >= 0xdc00 && u <= 0xdfff) return false // lone low\n if (u >= 0xd800 && u <= 0xdbff) {\n const nxt = c.charCodeAt(i + 1)\n if (!(nxt >= 0xdc00 && nxt <= 0xdfff)) return false // lone high\n i++\n }\n }\n const bytes = new TextEncoder().encode(c)\n if (bytes.length < 1 || bytes.length > 1024) return false\n for (const ch of c) {\n const cp = ch.codePointAt(0)!\n if (CC_15(cp) || CF_15(cp) || WHITE_SPACE_15.has(cp)) return false\n }\n return true\n}\n\nexport interface CarrierPrincipal {\n principal: string // did:key:z6Mk…, the control principal\n key: KeyPair // its Ed25519 pair (for the proofs of §5a.3)\n info: string // the derivation info, for auditability\n keyAgreement: null // declared, not omitted: Ed25519-only (§7a.1)\n}\n\n// Identity §7a.4 — derive the control principal for one relationship at\n// one carrier. `carrier` is C exactly as configured (byte-exact), `nonce`\n// is the relationship's 32-byte carrier nonce N from the register (§7a.3).\nexport async function carrierPrincipal (\n rootIkm: Uint8Array, carrier: string, nonce: Uint8Array,\n): Promise<CarrierPrincipal> {\n if (!validCarrierIdentifier(carrier)) throw new Error('invalid carrier identifier (7a.2)')\n if (nonce.length !== 32) throw new Error('carrier nonce must be 32 bytes (7a.3)')\n // M-3: the derivation reads its inputs at entry, once. Caller-held\n // buffers can be mutated while the HKDF awaits; copies make the\n // derived principal a function of the arguments as passed.\n const ikm = rootIkm.slice()\n const n = nonce.slice()\n const info = CARRIER_INFO_PREFIX + await mh(te.encode(carrier)) + await mh(n)\n const seed = await hkdf(ikm, info)\n const key = await edFromSeed(seed)\n return { principal: anchorOfEd(key.pubRaw), key, info, keyAgreement: null }\n}\n\nexport interface CarrierScopedIdentity {\n did: string // did:key:z6Mk…\n key: KeyPair\n info: string\n scope: 'connection' | 'egress'\n}\n\n// One connection DID / one egress identity per (relationship × carrier),\n// same derivation discipline and same input rules as the principal\n// (§7a.4), distinct prefix. Retired with the principal, never reused.\nexport async function carrierScopedIdentity (\n rootIkm: Uint8Array, carrier: string, nonce: Uint8Array,\n scope: 'connection' | 'egress',\n): Promise<CarrierScopedIdentity> {\n if (!validCarrierIdentifier(carrier)) throw new Error('invalid carrier identifier (7a.2)')\n if (nonce.length !== 32) throw new Error('carrier nonce must be 32 bytes (7a.3)')\n const ikm = rootIkm.slice()\n const n = nonce.slice()\n const prefix = scope === 'connection' ? CONNECTION_INFO_PREFIX : EGRESS_INFO_PREFIX\n const info = prefix + await mh(te.encode(carrier)) + await mh(n)\n const seed = await hkdf(ikm, info)\n const key = await edFromSeed(seed)\n return { did: anchorOfEd(key.pubRaw), key, info, scope }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA+BA,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,uBAAuB,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,10 @@
|
|
|
22
22
|
// carrier-identity the carrier-relationship principal (Identity §7a)
|
|
23
23
|
// carrier the carrier side of the port (Delivery §4.4 + §5a)
|
|
24
24
|
// holder the holder side: proofs, verdicts, recovery (§5a, §9.3)
|
|
25
|
+
// visibility Network Visibility 0.29 on Delivery 0.79 — the trust
|
|
26
|
+
// act, the blinded star, §6a continuity, the deniable
|
|
27
|
+
// ack (namespaced: `visibility.trust`, `.continuity`,
|
|
28
|
+
// `.acks`; graduated from /probe on 04.09.2026)
|
|
25
29
|
//
|
|
26
30
|
// Specification, schemas and vectors: https://rltp.real-life.org
|
|
27
31
|
export * from './core.js';
|
|
@@ -32,4 +36,5 @@ export * from './delivery.js';
|
|
|
32
36
|
export * from './carrier-identity.js';
|
|
33
37
|
export * from './carrier.js';
|
|
34
38
|
export * from './holder.js';
|
|
39
|
+
export * as visibility from './visibility.js';
|
|
35
40
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,EAAE;AACF,uEAAuE;AACvE,mEAAmE;AACnE,uEAAuE;AACvE,uEAAuE;AACvE,6BAA6B;AAC7B,EAAE;AACF,oEAAoE;AACpE,kEAAkE;AAClE,sEAAsE;AACtE,sEAAsE;AACtE,uEAAuE;AACvE,qEAAqE;AACrE,uBAAuB;AACvB,EAAE;AACF,oDAAoD;AACpD,mEAAmE;AACnE,+EAA+E;AAC/E,gFAAgF;AAChF,6EAA6E;AAC7E,wEAAwE;AACxE,yEAAyE;AACzE,8EAA8E;AAC9E,EAAE;AACF,iEAAiE;AAEjE,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,uBAAuB,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA","sourcesContent":["// @real-life/trust-protocol — the cryptographic core of RLTP.\n//\n// What this entry point IS: the wire-level primitives of the converged\n// layers, reproducing the shipped test vectors byte for byte — the\n// canonical form, the derivation of identity contexts under the closed\n// label registry, the encounter wire builders, the sealed envelope and\n// the generic receive chain.\n//\n// What it is NOT (yet): the layers' full state machines. Identity's\n// recovery derivation, Encounter's ceremony record and acceptance\n// machinery, Delivery's type-specific stages and residual bookkeeping\n// live in the specification and its conformance fixtures, not here. A\n// conformant implementation builds ON this module; importing it is not\n// yet conformance. The README states per module which casting's wire\n// forms it implements.\n//\n// core the form every artifact obeys\n// crypto the primitives, and the Data Integrity proof\n// identity context derivation under the closed registry (§6.1/§6.2)\n// encounter the ceremony's wire forms: challenges, cards, credentials\n// delivery the sealed envelope and the generic receive stages 1–4\n// carrier-identity the carrier-relationship principal (Identity §7a)\n// carrier the carrier side of the port (Delivery §4.4 + §5a)\n// holder the holder side: proofs, verdicts, recovery (§5a, §9.3)\n//\n// Specification, schemas and vectors: https://rltp.real-life.org\n\nexport * from './core.js'\nexport * from './crypto.js'\nexport * from './identity.js'\nexport * from './encounter.js'\nexport * from './delivery.js'\nexport * from './carrier-identity.js'\nexport * from './carrier.js'\nexport * from './holder.js'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,EAAE;AACF,uEAAuE;AACvE,mEAAmE;AACnE,uEAAuE;AACvE,uEAAuE;AACvE,6BAA6B;AAC7B,EAAE;AACF,oEAAoE;AACpE,kEAAkE;AAClE,sEAAsE;AACtE,sEAAsE;AACtE,uEAAuE;AACvE,qEAAqE;AACrE,uBAAuB;AACvB,EAAE;AACF,oDAAoD;AACpD,mEAAmE;AACnE,+EAA+E;AAC/E,gFAAgF;AAChF,6EAA6E;AAC7E,wEAAwE;AACxE,yEAAyE;AACzE,8EAA8E;AAC9E,2EAA2E;AAC3E,0EAA0E;AAC1E,0EAA0E;AAC1E,oEAAoE;AACpE,EAAE;AACF,iEAAiE;AAEjE,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,uBAAuB,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA","sourcesContent":["// @real-life/trust-protocol — the cryptographic core of RLTP.\n//\n// What this entry point IS: the wire-level primitives of the converged\n// layers, reproducing the shipped test vectors byte for byte — the\n// canonical form, the derivation of identity contexts under the closed\n// label registry, the encounter wire builders, the sealed envelope and\n// the generic receive chain.\n//\n// What it is NOT (yet): the layers' full state machines. Identity's\n// recovery derivation, Encounter's ceremony record and acceptance\n// machinery, Delivery's type-specific stages and residual bookkeeping\n// live in the specification and its conformance fixtures, not here. A\n// conformant implementation builds ON this module; importing it is not\n// yet conformance. The README states per module which casting's wire\n// forms it implements.\n//\n// core the form every artifact obeys\n// crypto the primitives, and the Data Integrity proof\n// identity context derivation under the closed registry (§6.1/§6.2)\n// encounter the ceremony's wire forms: challenges, cards, credentials\n// delivery the sealed envelope and the generic receive stages 1–4\n// carrier-identity the carrier-relationship principal (Identity §7a)\n// carrier the carrier side of the port (Delivery §4.4 + §5a)\n// holder the holder side: proofs, verdicts, recovery (§5a, §9.3)\n// visibility Network Visibility 0.29 on Delivery 0.79 — the trust\n// act, the blinded star, §6a continuity, the deniable\n// ack (namespaced: `visibility.trust`, `.continuity`,\n// `.acks`; graduated from /probe on 04.09.2026)\n//\n// Specification, schemas and vectors: https://rltp.real-life.org\n\nexport * from './core.js'\nexport * from './crypto.js'\nexport * from './identity.js'\nexport * from './encounter.js'\nexport * from './delivery.js'\nexport * from './carrier-identity.js'\nexport * from './carrier.js'\nexport * from './holder.js'\nexport * as visibility from './visibility.js'\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as C from './deps.js';
|
|
2
|
+
import type { Person } from './deps.js';
|
|
3
|
+
export declare const ACK_TYPE = "https://real-life.org/trust-tasks/delivery-ack/0.1";
|
|
4
|
+
/** the channel ack key — Section 5's derivation discipline, 4.2's info */
|
|
5
|
+
export declare function ackKey(ownCtx: any, counterpartKa: string, issuerAnchor: string, recipientAnchor: string): Promise<Uint8Array<ArrayBufferLike>>;
|
|
6
|
+
/**
|
|
7
|
+
* Build the sealed deniable ack for a document received on `contact`'s
|
|
8
|
+
* channel. `refDigest` is the acknowledged document's digest (the same
|
|
9
|
+
* digest the completed-effect cache keys on); `threadId` is the acked
|
|
10
|
+
* document's thread — the ack continues it (4.2).
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildAck(p: Person, contact: any, refDigest: string, threadId: string, when: number, ent?: any): Promise<{
|
|
13
|
+
to: any;
|
|
14
|
+
kind: string;
|
|
15
|
+
env: C.Envelope;
|
|
16
|
+
}>;
|
|
17
|
+
/**
|
|
18
|
+
* Verify a received deniable ack (4.2 consistency): MAC-form proof only,
|
|
19
|
+
* MAC under the arrival tuple's ack key, issuer = our counterpart on
|
|
20
|
+
* that tuple, recipient = our own pair anchor. Returns { ref, threadId }
|
|
21
|
+
* or null — the caller matches ref against what it actually sent.
|
|
22
|
+
*/
|
|
23
|
+
export declare function verifyAck(p: Person, contact: any, doc: any): Promise<{
|
|
24
|
+
ref: string;
|
|
25
|
+
threadId: string;
|
|
26
|
+
} | null>;
|
|
27
|
+
//# sourceMappingURL=acks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acks.d.ts","sourceRoot":"","sources":["../../src/probe/acks.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,CAAC,MAAM,WAAW,CAAA;AAC9B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAIvC,eAAO,MAAM,QAAQ,uDAAuD,CAAA;AAa5E,0EAA0E;AAC1E,wBAAsB,MAAM,CAAE,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,wCAI9G;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,GAAQ;;;;GAcxH;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAgCrH"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// acks — the deniable delivery acknowledgement (Delivery 4.2/4.4, the
|
|
2
|
+
// acknowledgement class rule) for the probe world. The ack DOCUMENT is
|
|
3
|
+
// the real, registered wire form (`delivery-ack/0.1`), and the key
|
|
4
|
+
// regime is the normative one — byte-compatible with
|
|
5
|
+
// vectors/delivery-ack.json and lib/test/vectors4.test.mjs: one
|
|
6
|
+
// channel-keyed derivation for every DV-type ack, never the payload's
|
|
7
|
+
// internal MAC structure.
|
|
8
|
+
//
|
|
9
|
+
// k = HKDF-SHA-256(ikm = X25519(pairX_issuer, pairX_recipient),
|
|
10
|
+
// salt = empty, info = "rltp/v1/delivery/mac/ack/"
|
|
11
|
+
// || issuerPairAnchor || "/" || recipientPairAnchor,
|
|
12
|
+
// 32 bytes; all-zero shared secret rejected)
|
|
13
|
+
// proof = { mac: HMAC-SHA-256 over JCS(document without proof) }
|
|
14
|
+
//
|
|
15
|
+
// Deniable by construction: either relationship party can compute the
|
|
16
|
+
// MAC — for DV payloads the ack is evidence to the sender alone, never
|
|
17
|
+
// an attestation toward anyone else (4.2).
|
|
18
|
+
import { jcs, makeValidator } from '../core.js';
|
|
19
|
+
import { SCHEMAS } from '../schemas.js';
|
|
20
|
+
import * as C from './deps.js';
|
|
21
|
+
const te = new TextEncoder();
|
|
22
|
+
const S = globalThis.crypto.subtle;
|
|
23
|
+
export const ACK_TYPE = 'https://real-life.org/trust-tasks/delivery-ack/0.1';
|
|
24
|
+
const V = makeValidator(SCHEMAS);
|
|
25
|
+
const schemaOk = (file, data) => V.validate(data, SCHEMAS[file], SCHEMAS[file]).length === 0;
|
|
26
|
+
const hmacU = async (key, msg) => {
|
|
27
|
+
const k = await S.importKey('raw', key, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
|
|
28
|
+
return 'u' + C.b64uOf(new Uint8Array(await S.sign('HMAC', k, te.encode(msg))));
|
|
29
|
+
};
|
|
30
|
+
const contactKeyOf = (p, contact) => {
|
|
31
|
+
for (const [k, c] of p.contacts)
|
|
32
|
+
if (c === contact)
|
|
33
|
+
return k;
|
|
34
|
+
return undefined;
|
|
35
|
+
};
|
|
36
|
+
/** the channel ack key — Section 5's derivation discipline, 4.2's info */
|
|
37
|
+
export async function ackKey(ownCtx, counterpartKa, issuerAnchor, recipientAnchor) {
|
|
38
|
+
const shared = await C.ecdh(ownCtx.x.priv, C.xRawOfMk(counterpartKa));
|
|
39
|
+
if (shared.every((b) => b === 0))
|
|
40
|
+
throw new Error('all-zero X25519 output');
|
|
41
|
+
return C.hkdf(shared, 'rltp/v1/delivery/mac/ack/' + issuerAnchor + '/' + recipientAnchor);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Build the sealed deniable ack for a document received on `contact`'s
|
|
45
|
+
* channel. `refDigest` is the acknowledged document's digest (the same
|
|
46
|
+
* digest the completed-effect cache keys on); `threadId` is the acked
|
|
47
|
+
* document's thread — the ack continues it (4.2).
|
|
48
|
+
*/
|
|
49
|
+
export async function buildAck(p, contact, refDigest, threadId, when, ent = {}) {
|
|
50
|
+
const own = contact.channel.own;
|
|
51
|
+
const doc = {
|
|
52
|
+
id: ent.ackId ?? globalThis.crypto.randomUUID(),
|
|
53
|
+
type: ACK_TYPE,
|
|
54
|
+
issuer: own.anchor, // = the acked document's recipient (4.2)
|
|
55
|
+
recipient: contactKeyOf(p, contact),
|
|
56
|
+
threadId,
|
|
57
|
+
issuedAt: C.iso(when),
|
|
58
|
+
payload: { ref: refDigest, meaning: 'received' },
|
|
59
|
+
};
|
|
60
|
+
const k = await ackKey(own, contact.channel.counterpartKa, doc.issuer, doc.recipient);
|
|
61
|
+
const document = { ...doc, proof: { mac: await hmacU(k, jcs(doc)) } };
|
|
62
|
+
return { to: contact, kind: 'delivery-ack/0.1 (deniabel, MAC unter dem Kanal-Ack-Key)', env: await C.seal(document, contact.channel.counterpartKa, ent) };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Verify a received deniable ack (4.2 consistency): MAC-form proof only,
|
|
66
|
+
* MAC under the arrival tuple's ack key, issuer = our counterpart on
|
|
67
|
+
* that tuple, recipient = our own pair anchor. Returns { ref, threadId }
|
|
68
|
+
* or null — the caller matches ref against what it actually sent.
|
|
69
|
+
*/
|
|
70
|
+
export async function verifyAck(p, contact, doc) {
|
|
71
|
+
try {
|
|
72
|
+
if (doc?.type !== ACK_TYPE)
|
|
73
|
+
return null;
|
|
74
|
+
// STUFENORDNUNG (Review 33, B-2): erst das DOKUMENTPROFIL + der
|
|
75
|
+
// recipient (Stufe 5), dann das Payload-Schema (Stufe 7), dann die
|
|
76
|
+
// Typ-Konsistenzregeln (Stufe 8), der MAC zuletzt
|
|
77
|
+
// — Stufe 5: Dokument-Schema, geschlossene Form, Proof-Form,
|
|
78
|
+
// Kalender, recipient = eigener Anker
|
|
79
|
+
if (!schemaOk('rltp-delivery-document.schema.json', doc))
|
|
80
|
+
return null;
|
|
81
|
+
if (!C.shaped(doc, { id: 'string', issuer: 'string', recipient: 'string', threadId: 'string', issuedAt: 'string', payload: 'object', proof: 'object' }))
|
|
82
|
+
return null;
|
|
83
|
+
// geschlossene Form + das OPTIONALE ceremony-Feld (Review 19, B-2:
|
|
84
|
+
// „ceremony — OPTIONAL, and entirely unconstrained"); der MAC läuft
|
|
85
|
+
// über JCS(Dokument ohne proof) und deckt es mit ab
|
|
86
|
+
if (Object.keys(doc).some((k) => !['id', 'type', 'issuer', 'recipient', 'threadId', 'issuedAt', 'payload', 'proof', 'ceremony'].includes(k)))
|
|
87
|
+
return null;
|
|
88
|
+
if (Object.keys(doc.proof).length !== 1)
|
|
89
|
+
return null;
|
|
90
|
+
// class rule: the MAC form and nothing else — a signature-form or
|
|
91
|
+
// hybrid proof for a DV payload is invalid (4.2/4.4)
|
|
92
|
+
if (typeof doc.proof.mac !== 'string' || doc.proof.proofValue !== undefined)
|
|
93
|
+
return null;
|
|
94
|
+
if (!C.calOK(doc.issuedAt))
|
|
95
|
+
return null; // Kalender-Validität (Review 12, B-3)
|
|
96
|
+
if (doc.recipient !== contact.channel.own.anchor)
|
|
97
|
+
return null;
|
|
98
|
+
// — Stufe 7: Payload-Schema
|
|
99
|
+
if (!schemaOk('payload-delivery-ack.schema.json', doc.payload))
|
|
100
|
+
return null;
|
|
101
|
+
// — Stufe 8: enactment-Profilregel (Review 20, B-2: ein Ack
|
|
102
|
+
// umschließt kein Bindungsmaterial), issuer-Bindung, meaning
|
|
103
|
+
if (doc.ceremony?.enactment !== undefined)
|
|
104
|
+
return null;
|
|
105
|
+
if (doc.issuer !== contactKeyOf(p, contact))
|
|
106
|
+
return null;
|
|
107
|
+
if (!C.shaped(doc.payload, { ref: 'string', meaning: 'string' }) || doc.payload.meaning !== 'received')
|
|
108
|
+
return null;
|
|
109
|
+
const { proof, ...rest } = doc;
|
|
110
|
+
const k = await ackKey(contact.channel.own, contact.channel.counterpartKa, doc.issuer, doc.recipient);
|
|
111
|
+
if ((await hmacU(k, jcs(rest))) !== proof.mac)
|
|
112
|
+
return null;
|
|
113
|
+
return { ref: doc.payload.ref, threadId: doc.threadId };
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=acks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acks.js","sourceRoot":"","sources":["../../src/probe/acks.ts"],"names":[],"mappings":"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","sourcesContent":["// acks — the deniable delivery acknowledgement (Delivery 4.2/4.4, the\n// acknowledgement class rule) for the probe world. The ack DOCUMENT is\n// the real, registered wire form (`delivery-ack/0.1`), and the key\n// regime is the normative one — byte-compatible with\n// vectors/delivery-ack.json and lib/test/vectors4.test.mjs: one\n// channel-keyed derivation for every DV-type ack, never the payload's\n// internal MAC structure.\n//\n// k = HKDF-SHA-256(ikm = X25519(pairX_issuer, pairX_recipient),\n// salt = empty, info = \"rltp/v1/delivery/mac/ack/\"\n// || issuerPairAnchor || \"/\" || recipientPairAnchor,\n// 32 bytes; all-zero shared secret rejected)\n// proof = { mac: HMAC-SHA-256 over JCS(document without proof) }\n//\n// Deniable by construction: either relationship party can compute the\n// MAC — for DV payloads the ack is evidence to the sender alone, never\n// an attestation toward anyone else (4.2).\nimport { jcs, makeValidator } from '../core.js'\nimport { SCHEMAS } from '../schemas.js'\nimport * as C from './deps.js'\nimport type { Person } from './deps.js'\n\nconst te = new TextEncoder()\nconst S = globalThis.crypto.subtle\nexport const ACK_TYPE = 'https://real-life.org/trust-tasks/delivery-ack/0.1'\n\nconst V = makeValidator(SCHEMAS)\nconst schemaOk = (file: string, data: any) => V.validate(data, SCHEMAS[file], SCHEMAS[file]).length === 0\nconst hmacU = async (key: Uint8Array, msg: string) => {\n const k = await S.importKey('raw', key, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'])\n return 'u' + C.b64uOf(new Uint8Array(await S.sign('HMAC', k, te.encode(msg))))\n}\nconst contactKeyOf = (p: Person, contact: any) => {\n for (const [k, c] of p.contacts) if (c === contact) return k\n return undefined\n}\n\n/** the channel ack key — Section 5's derivation discipline, 4.2's info */\nexport async function ackKey (ownCtx: any, counterpartKa: string, issuerAnchor: string, recipientAnchor: string) {\n const shared = await C.ecdh(ownCtx.x.priv, C.xRawOfMk(counterpartKa)!)\n if (shared.every((b: number) => b === 0)) throw new Error('all-zero X25519 output')\n return C.hkdf(shared, 'rltp/v1/delivery/mac/ack/' + issuerAnchor + '/' + recipientAnchor)\n}\n\n/**\n * Build the sealed deniable ack for a document received on `contact`'s\n * channel. `refDigest` is the acknowledged document's digest (the same\n * digest the completed-effect cache keys on); `threadId` is the acked\n * document's thread — the ack continues it (4.2).\n */\nexport async function buildAck (p: Person, contact: any, refDigest: string, threadId: string, when: number, ent: any = {}) {\n const own = contact.channel.own\n const doc = {\n id: ent.ackId ?? globalThis.crypto.randomUUID(),\n type: ACK_TYPE,\n issuer: own.anchor, // = the acked document's recipient (4.2)\n recipient: contactKeyOf(p, contact),\n threadId,\n issuedAt: C.iso(when),\n payload: { ref: refDigest, meaning: 'received' },\n }\n const k = await ackKey(own, contact.channel.counterpartKa, doc.issuer, doc.recipient!)\n const document = { ...doc, proof: { mac: await hmacU(k, jcs(doc)) } }\n return { to: contact, kind: 'delivery-ack/0.1 (deniabel, MAC unter dem Kanal-Ack-Key)', env: await C.seal(document, contact.channel.counterpartKa, ent) }\n}\n\n/**\n * Verify a received deniable ack (4.2 consistency): MAC-form proof only,\n * MAC under the arrival tuple's ack key, issuer = our counterpart on\n * that tuple, recipient = our own pair anchor. Returns { ref, threadId }\n * or null — the caller matches ref against what it actually sent.\n */\nexport async function verifyAck (p: Person, contact: any, doc: any): Promise<{ ref: string, threadId: string } | null> {\n try {\n if (doc?.type !== ACK_TYPE) return null\n // STUFENORDNUNG (Review 33, B-2): erst das DOKUMENTPROFIL + der\n // recipient (Stufe 5), dann das Payload-Schema (Stufe 7), dann die\n // Typ-Konsistenzregeln (Stufe 8), der MAC zuletzt\n // — Stufe 5: Dokument-Schema, geschlossene Form, Proof-Form,\n // Kalender, recipient = eigener Anker\n if (!schemaOk('rltp-delivery-document.schema.json', doc)) return null\n if (!C.shaped(doc, { id: 'string', issuer: 'string', recipient: 'string', threadId: 'string', issuedAt: 'string', payload: 'object', proof: 'object' })) return null\n // geschlossene Form + das OPTIONALE ceremony-Feld (Review 19, B-2:\n // „ceremony — OPTIONAL, and entirely unconstrained\"); der MAC läuft\n // über JCS(Dokument ohne proof) und deckt es mit ab\n if (Object.keys(doc).some((k) => !['id', 'type', 'issuer', 'recipient', 'threadId', 'issuedAt', 'payload', 'proof', 'ceremony'].includes(k))) return null\n if (Object.keys(doc.proof).length !== 1) return null\n // class rule: the MAC form and nothing else — a signature-form or\n // hybrid proof for a DV payload is invalid (4.2/4.4)\n if (typeof doc.proof.mac !== 'string' || doc.proof.proofValue !== undefined) return null\n if (!C.calOK(doc.issuedAt)) return null // Kalender-Validität (Review 12, B-3)\n if (doc.recipient !== contact.channel.own.anchor) return null\n // — Stufe 7: Payload-Schema\n if (!schemaOk('payload-delivery-ack.schema.json', doc.payload)) return null\n // — Stufe 8: enactment-Profilregel (Review 20, B-2: ein Ack\n // umschließt kein Bindungsmaterial), issuer-Bindung, meaning\n if (doc.ceremony?.enactment !== undefined) return null\n if (doc.issuer !== contactKeyOf(p, contact)) return null\n if (!C.shaped(doc.payload, { ref: 'string', meaning: 'string' }) || doc.payload.meaning !== 'received') return null\n const { proof, ...rest } = doc\n const k = await ackKey(contact.channel.own, contact.channel.counterpartKa, doc.issuer, doc.recipient)\n if ((await hmacU(k, jcs(rest))) !== proof.mac) return null\n return { ref: doc.payload.ref, threadId: doc.threadId }\n } catch { return null }\n}\n"]}
|
|
@@ -4,96 +4,17 @@ export declare const snapshotPriors: (p: Person) => {
|
|
|
4
4
|
own: any[];
|
|
5
5
|
counterpart: string[];
|
|
6
6
|
};
|
|
7
|
-
export declare function buildProbe(p: Person, newKey: string, ent?: any): Promise<{
|
|
7
|
+
export declare function buildProbe(p: Person, newKey: string, when: number, ent?: any): Promise<{
|
|
8
8
|
to: any;
|
|
9
9
|
kind: string;
|
|
10
10
|
env: C.Envelope;
|
|
11
11
|
}[] | null>;
|
|
12
|
-
export declare function receiveContinuity(p: Person, env: any, when: number, ent?: any): Promise<
|
|
13
|
-
handled: boolean;
|
|
14
|
-
partial: boolean;
|
|
15
|
-
error?: undefined;
|
|
16
|
-
matches?: undefined;
|
|
17
|
-
chained?: undefined;
|
|
18
|
-
name?: undefined;
|
|
19
|
-
outbound?: undefined;
|
|
20
|
-
outboundError?: undefined;
|
|
21
|
-
} | {
|
|
22
|
-
handled: boolean;
|
|
23
|
-
matches: number;
|
|
24
|
-
error?: undefined;
|
|
25
|
-
partial?: undefined;
|
|
26
|
-
chained?: undefined;
|
|
27
|
-
name?: undefined;
|
|
28
|
-
outbound?: undefined;
|
|
29
|
-
outboundError?: undefined;
|
|
30
|
-
} | {
|
|
31
|
-
handled: boolean;
|
|
32
|
-
matches: number;
|
|
33
|
-
chained: boolean;
|
|
34
|
-
name: any;
|
|
35
|
-
outbound: {
|
|
36
|
-
to: any;
|
|
37
|
-
kind: string;
|
|
38
|
-
env: C.Envelope;
|
|
39
|
-
}[];
|
|
40
|
-
outboundError: string | undefined;
|
|
41
|
-
error?: undefined;
|
|
42
|
-
partial?: undefined;
|
|
43
|
-
} | {
|
|
44
|
-
handled: boolean;
|
|
45
|
-
error: string;
|
|
46
|
-
chained?: undefined;
|
|
47
|
-
name?: undefined;
|
|
48
|
-
outbound?: undefined;
|
|
49
|
-
outboundError?: undefined;
|
|
50
|
-
} | {
|
|
51
|
-
handled: boolean;
|
|
52
|
-
chained: boolean;
|
|
53
|
-
name: any;
|
|
54
|
-
outbound: {
|
|
55
|
-
to: any;
|
|
56
|
-
kind: string;
|
|
57
|
-
env: C.Envelope;
|
|
58
|
-
}[];
|
|
59
|
-
outboundError: string;
|
|
60
|
-
error?: undefined;
|
|
61
|
-
} | {
|
|
62
|
-
handled: boolean;
|
|
63
|
-
chained: boolean;
|
|
64
|
-
name: any;
|
|
65
|
-
outbound: {
|
|
66
|
-
to: any;
|
|
67
|
-
kind: string;
|
|
68
|
-
env: C.Envelope;
|
|
69
|
-
}[];
|
|
70
|
-
error?: undefined;
|
|
71
|
-
outboundError?: undefined;
|
|
72
|
-
} | {
|
|
73
|
-
handled: boolean;
|
|
74
|
-
doc: any;
|
|
75
|
-
} | {
|
|
76
|
-
handled: boolean;
|
|
77
|
-
duplicate: boolean;
|
|
78
|
-
} | {
|
|
79
|
-
handled: boolean;
|
|
80
|
-
duplicate?: undefined;
|
|
81
|
-
}>;
|
|
12
|
+
export declare function receiveContinuity(p: Person, env: any, when: number, ent?: any): Promise<any>;
|
|
82
13
|
/**
|
|
83
14
|
* The host's producing call for a mapping the receiver still owes
|
|
84
15
|
* (review 6, B-3): a transient seal failure during probe/mapping
|
|
85
16
|
* handling persists the obligation in contMappingDue; this call — not a
|
|
86
17
|
* redelivery, which the freshness rule forbids — builds and returns it.
|
|
87
18
|
*/
|
|
88
|
-
export declare function flushContinuity(p: Person, newKey: string, when: number, ent?: any): Promise<
|
|
89
|
-
outbound: never[];
|
|
90
|
-
pending: boolean;
|
|
91
|
-
} | {
|
|
92
|
-
outbound: {
|
|
93
|
-
to: any;
|
|
94
|
-
kind: string;
|
|
95
|
-
env: C.Envelope;
|
|
96
|
-
}[];
|
|
97
|
-
pending?: undefined;
|
|
98
|
-
}>;
|
|
19
|
+
export declare function flushContinuity(p: Person, newKey: string, when: number, ent?: any): Promise<any>;
|
|
99
20
|
//# sourceMappingURL=continuity.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"continuity.d.ts","sourceRoot":"","sources":["../../src/probe/continuity.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"continuity.d.ts","sourceRoot":"","sources":["../../src/probe/continuity.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,CAAC,MAAM,WAAW,CAAA;AAC9B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAoBvC,eAAO,MAAM,cAAc,GAAI,GAAG,MAAM;;;CAGtC,CAAA;AAOF,wBAAsB,UAAU,CAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,GAAQ;;;;YA0DvF;AAwID,wBAAsB,iBAAiB,CAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,GAAQ,gBAwDxF;AA4PD;;;;;GAKG;AACH,wBAAsB,eAAe,CAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,GAAQ,gBA6E5F"}
|