@real-life/trust-protocol 0.1.0 → 0.1.1
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 +6 -1
- package/dist/carrier-identity.d.ts +11 -0
- package/dist/carrier-identity.d.ts.map +1 -0
- package/dist/carrier-identity.js +85 -0
- package/dist/carrier-identity.js.map +1 -0
- package/dist/carrier.d.ts +157 -0
- package/dist/carrier.d.ts.map +1 -0
- package/dist/carrier.js +577 -0
- package/dist/carrier.js.map +1 -0
- package/dist/holder.d.ts +42 -0
- package/dist/holder.d.ts.map +1 -0
- package/dist/holder.js +92 -0
- package/dist/holder.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -7
- package/dist/index.js.map +1 -1
- package/dist/probe.d.ts +1 -0
- package/dist/probe.d.ts.map +1 -1
- package/dist/probe.js +1 -1
- package/dist/probe.js.map +1 -1
- package/dist/wire.d.ts +573 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +2 -0
- package/dist/wire.js.map +1 -0
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -32,6 +32,9 @@ look in the code:
|
|
|
32
32
|
| `identity` | Identity Layer | One root seed, every context derived — community anchor, pair anchor per relationship, member anchor per group. Contexts never link without their holder's deliberate act. |
|
|
33
33
|
| `encounter` | Encounter Layer | The ceremony under fresh-always pair anchors: challenges, contact cards, the enactment binding both sides compute independently, encounter credentials. |
|
|
34
34
|
| `delivery` | Delivery Contract | The sealed envelope, and the receive chain in its declared order — size bound *before* decryption, envelope form, decryption, parse and digest over the canonical form, completed-effect cache. |
|
|
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
|
+
| `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
|
+
| `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. |
|
|
35
38
|
|
|
36
39
|
Everything is re-exported from the package root; the table is a map, not an
|
|
37
40
|
import instruction.
|
|
@@ -74,7 +77,9 @@ it deliberately does not:
|
|
|
74
77
|
|
|
75
78
|
| Module (0.1.x) | Casting | Implemented | Not in this package |
|
|
76
79
|
|---|---|---|---|
|
|
77
|
-
| `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),
|
|
80
|
+
| `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
|
+
| `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.69 (§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) |
|
|
78
83
|
| `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 |
|
|
79
84
|
| `delivery` | Delivery 0.64 | the sealed envelope (§5) and the generic receive stages 1–4 | the type-specific stages, residual bookkeeping, transport adapters |
|
|
80
85
|
| `core`, `crypto` | cross-layer | canonical form, digest equality, timestamps, validator; primitives + `eddsa-jcs-2022` proof | — |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { KeyPair } from './crypto.js';
|
|
2
|
+
export declare const CARRIER_INFO_PREFIX = "rltp/v1/carrier-relationship/ed25519/v1/";
|
|
3
|
+
export declare function validCarrierIdentifier(c: unknown): c is string;
|
|
4
|
+
export interface CarrierPrincipal {
|
|
5
|
+
principal: string;
|
|
6
|
+
key: KeyPair;
|
|
7
|
+
info: string;
|
|
8
|
+
keyAgreement: null;
|
|
9
|
+
}
|
|
10
|
+
export declare function carrierPrincipal(rootIkm: Uint8Array, carrier: string, nonce: Uint8Array): Promise<CarrierPrincipal>;
|
|
11
|
+
//# sourceMappingURL=carrier-identity.d.ts.map
|
|
@@ -0,0 +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;AA4B7E,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,CAO3B"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// carrier-identity — Identity §7a: the carrier-relationship identity class.
|
|
2
|
+
//
|
|
3
|
+
// One control principal per (relationship × carrier), Ed25519-only. The
|
|
4
|
+
// derivation shares no computable relation with the relationship's other
|
|
5
|
+
// principals or with its `rkid` — that absence is the privacy property
|
|
6
|
+
// the whole class exists for (§7a.5), and it is why registration must
|
|
7
|
+
// PROVE the binding instead of computing it (Delivery §5a.3).
|
|
8
|
+
//
|
|
9
|
+
// info = "rltp/v1/carrier-relationship/ed25519/v1/" || Dc || Dn
|
|
10
|
+
// where Dc = multihash(sha2-256, UTF-8 of the configured carrier
|
|
11
|
+
// identifier C) and Dn = multihash(sha2-256, 32-byte carrier nonce N),
|
|
12
|
+
// each rendered as 'u' + base64url — exactly 47 characters, so the two
|
|
13
|
+
// parts are length-fixed and no concatenation ambiguity exists (§7a.4).
|
|
14
|
+
//
|
|
15
|
+
// NO key-agreement key is derived for this class: sealing stays at the
|
|
16
|
+
// `rkid` (§7a.1), and a carrier that never holds a decryption key can
|
|
17
|
+
// never be asked to use one.
|
|
18
|
+
import { b64uOf, cat } from './crypto.js';
|
|
19
|
+
import { sha, hkdf, edFromSeed, anchorOfEd } from './crypto.js';
|
|
20
|
+
import { WHITE_SPACE_15 } from './unicode15.js';
|
|
21
|
+
const te = new TextEncoder();
|
|
22
|
+
export const CARRIER_INFO_PREFIX = 'rltp/v1/carrier-relationship/ed25519/v1/';
|
|
23
|
+
// multihash(sha2-256) in base64url — the digest form Identity §7a.4 fixes
|
|
24
|
+
const mh = async (bytes) => 'u' + b64uOf(cat(Uint8Array.from([0x12, 0x20]), await sha(bytes)));
|
|
25
|
+
// Identity §7a.2 — the ordered validation pipeline for C, fail closed
|
|
26
|
+
// and NO normalization (the deliberate difference to §6.2): valid
|
|
27
|
+
// Unicode scalar values only (unpaired surrogates never repaired),
|
|
28
|
+
// 1..1024 UTF-8 BYTES, and no Cc, Cf or White_Space code point anywhere.
|
|
29
|
+
//
|
|
30
|
+
// The category tables are PINNED to Unicode 15.0 (port-review-2 M-6):
|
|
31
|
+
// evaluating against the platform's \p{...} data would let the same
|
|
32
|
+
// identifier derive a principal on one runtime and be rejected on
|
|
33
|
+
// another the moment a Unicode revision moves a code point — the exact
|
|
34
|
+
// defect the persona repertoire (unicode15.ts) already closed for §6.2.
|
|
35
|
+
// Cc is the stable C0/C1 block; Cf is the 170-code-point Unicode-15.0
|
|
36
|
+
// set, enumerated below; White_Space is unicode15.ts's pinned set.
|
|
37
|
+
const CC_15 = (cp) => cp <= 0x1f || (cp >= 0x7f && cp <= 0x9f);
|
|
38
|
+
const CF_15_RANGES = [
|
|
39
|
+
[0x00ad, 0x00ad], [0x0600, 0x0605], [0x061c, 0x061c], [0x06dd, 0x06dd],
|
|
40
|
+
[0x070f, 0x070f], [0x0890, 0x0891], [0x08e2, 0x08e2], [0x180e, 0x180e],
|
|
41
|
+
[0x200b, 0x200f], [0x202a, 0x202e], [0x2060, 0x2064], [0x2066, 0x206f],
|
|
42
|
+
[0xfeff, 0xfeff], [0xfff9, 0xfffb], [0x110bd, 0x110bd], [0x110cd, 0x110cd],
|
|
43
|
+
[0x13430, 0x1343f], [0x1bca0, 0x1bca3], [0x1d173, 0x1d17a],
|
|
44
|
+
[0xe0001, 0xe0001], [0xe0020, 0xe007f],
|
|
45
|
+
];
|
|
46
|
+
const CF_15 = (cp) => CF_15_RANGES.some(([a, b]) => cp >= a && cp <= b);
|
|
47
|
+
export function validCarrierIdentifier(c) {
|
|
48
|
+
if (typeof c !== 'string' || c.length === 0)
|
|
49
|
+
return false;
|
|
50
|
+
// scalar values: an unpaired surrogate is not a Unicode string
|
|
51
|
+
for (let i = 0; i < c.length; i++) {
|
|
52
|
+
const u = c.charCodeAt(i);
|
|
53
|
+
if (u >= 0xdc00 && u <= 0xdfff)
|
|
54
|
+
return false; // lone low
|
|
55
|
+
if (u >= 0xd800 && u <= 0xdbff) {
|
|
56
|
+
const nxt = c.charCodeAt(i + 1);
|
|
57
|
+
if (!(nxt >= 0xdc00 && nxt <= 0xdfff))
|
|
58
|
+
return false; // lone high
|
|
59
|
+
i++;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const bytes = new TextEncoder().encode(c);
|
|
63
|
+
if (bytes.length < 1 || bytes.length > 1024)
|
|
64
|
+
return false;
|
|
65
|
+
for (const ch of c) {
|
|
66
|
+
const cp = ch.codePointAt(0);
|
|
67
|
+
if (CC_15(cp) || CF_15(cp) || WHITE_SPACE_15.has(cp))
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
// Identity §7a.4 — derive the control principal for one relationship at
|
|
73
|
+
// one carrier. `carrier` is C exactly as configured (byte-exact), `nonce`
|
|
74
|
+
// is the relationship's 32-byte carrier nonce N from the register (§7a.3).
|
|
75
|
+
export async function carrierPrincipal(rootIkm, carrier, nonce) {
|
|
76
|
+
if (!validCarrierIdentifier(carrier))
|
|
77
|
+
throw new Error('invalid carrier identifier (7a.2)');
|
|
78
|
+
if (nonce.length !== 32)
|
|
79
|
+
throw new Error('carrier nonce must be 32 bytes (7a.3)');
|
|
80
|
+
const info = CARRIER_INFO_PREFIX + await mh(te.encode(carrier)) + await mh(nonce);
|
|
81
|
+
const seed = await hkdf(rootIkm, info);
|
|
82
|
+
const key = await edFromSeed(seed);
|
|
83
|
+
return { principal: anchorOfEd(key.pubRaw), key, info, keyAgreement: null };
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=carrier-identity.js.map
|
|
@@ -0,0 +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"]}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
export interface CarrierDeclaration {
|
|
2
|
+
carrier: string;
|
|
3
|
+
orphanHorizonMs: number;
|
|
4
|
+
giveUpHorizonMs: number;
|
|
5
|
+
challengeLifetimeMs: number;
|
|
6
|
+
queueFloorBytes: number;
|
|
7
|
+
maxQueueBytes: number;
|
|
8
|
+
maxBindingTombstones: number;
|
|
9
|
+
statusHorizonMs: number;
|
|
10
|
+
}
|
|
11
|
+
/** §11: an out-of-domain declaration REJECTS — it never half-applies. */
|
|
12
|
+
export declare function validateDeclaration(d: CarrierDeclaration): string[];
|
|
13
|
+
export declare const CARRIER_ROLE_URI = "https://real-life.org/trust-tasks/delivery-carrier/0.1";
|
|
14
|
+
export declare const PROOF_V = "rltp-carrier-proof/0.3";
|
|
15
|
+
export interface CarrierPolicy {
|
|
16
|
+
/** shared admission gate — the one unknown-address traffic competes
|
|
17
|
+
* for. NEVER invoked for a request naming a held binding. */
|
|
18
|
+
admitNew?: () => boolean;
|
|
19
|
+
/** per-binding gate for requests naming a HELD rkid (guarantee 4). */
|
|
20
|
+
admitHeld?: (rkid: string) => boolean;
|
|
21
|
+
/** per-queue submission meter — the only resource hook reachable below
|
|
22
|
+
* the floor (guarantee 5); DO-6 lives here. A duplicate charges it
|
|
23
|
+
* like an admitted submission (§5a.5) and stores nothing. */
|
|
24
|
+
meterQueue?: (rkid: string, bytes: number) => boolean;
|
|
25
|
+
/** global occupancy — s6, unreachable below the floor. */
|
|
26
|
+
hasCapacity?: (bytes: number) => boolean;
|
|
27
|
+
/** room for one more binding — r4, never consulted for a held one. */
|
|
28
|
+
hasBindingRoom?: () => boolean;
|
|
29
|
+
}
|
|
30
|
+
export type RegistrationVerdict = {
|
|
31
|
+
verdict: 'registered' | 'registered(idempotent)' | 'rebound';
|
|
32
|
+
} | {
|
|
33
|
+
verdict: 'refused(malformed)' | 'refused(possession-failed)';
|
|
34
|
+
} | {
|
|
35
|
+
verdict: 'refused(stale-generation)';
|
|
36
|
+
heldGeneration: number;
|
|
37
|
+
} | {
|
|
38
|
+
verdict: 'registration-refused(capacity)' | 'refused(admission-resource)';
|
|
39
|
+
retriable: true;
|
|
40
|
+
};
|
|
41
|
+
export type SessionVerdict = {
|
|
42
|
+
verdict: 'served';
|
|
43
|
+
} | {
|
|
44
|
+
verdict: 'refused(no-such-queue)' | 'refused(malformed)' | 'refused(possession-failed)';
|
|
45
|
+
} | {
|
|
46
|
+
verdict: 'refused(admission-resource)';
|
|
47
|
+
retriable: true;
|
|
48
|
+
};
|
|
49
|
+
export type SubmissionVerdict = {
|
|
50
|
+
verdict: 'admitted' | 'duplicate';
|
|
51
|
+
} | {
|
|
52
|
+
verdict: 'refused(no-such-queue)' | 'refused(bounds)';
|
|
53
|
+
} | {
|
|
54
|
+
verdict: 'refused(admission-resource)' | 'refused(queue-saturated)' | 'refused(capacity)';
|
|
55
|
+
retriable: true;
|
|
56
|
+
};
|
|
57
|
+
export interface CarrierProof {
|
|
58
|
+
v: string;
|
|
59
|
+
type: string;
|
|
60
|
+
purpose: 'register' | 'rebind' | 'collect' | 'conclude';
|
|
61
|
+
carrier: string;
|
|
62
|
+
principal: string;
|
|
63
|
+
rkid: string;
|
|
64
|
+
generation?: number;
|
|
65
|
+
principalChallenge: string;
|
|
66
|
+
addressChallenge?: string;
|
|
67
|
+
sig: string;
|
|
68
|
+
}
|
|
69
|
+
export declare const canonicalGenerationSpelling: (raw: string) => boolean;
|
|
70
|
+
/** r1, the SYNTACTIC half only — no cryptography happens here, so a
|
|
71
|
+
* request refused at r1 or r2 has cost the carrier no key operation
|
|
72
|
+
* (guarantee 3). `rawGeneration` is REQUIRED for register/rebind: a
|
|
73
|
+
* parsed number cannot carry its own spelling, and an adapter that
|
|
74
|
+
* cannot supply the received bytes cannot claim the check (round-44
|
|
75
|
+
* M-4 of the port review: optional was fail-open). */
|
|
76
|
+
export declare function checkProofShape(p: CarrierProof, expectedCarrier: string, rawGeneration?: string): 'refused(malformed)' | null;
|
|
77
|
+
/** compatibility shim for the shape+signature question alone (tests,
|
|
78
|
+
* tooling): stateless, no challenge semantics. */
|
|
79
|
+
export declare function verifyProofShape(p: CarrierProof, expectedCarrier: string, rawGeneration?: string): Promise<'refused(malformed)' | 'refused(possession-failed)' | null>;
|
|
80
|
+
export declare function checkEnvelopeBytes(bytes: Uint8Array, rkid: string): boolean;
|
|
81
|
+
export interface CarrierEvents {
|
|
82
|
+
onRelease?: (rkid: string, tombstoneGeneration: number) => void;
|
|
83
|
+
onGiveUp?: (rkid: string, digest: string) => void;
|
|
84
|
+
onEvict?: (rkid: string) => void;
|
|
85
|
+
}
|
|
86
|
+
export declare class Carrier {
|
|
87
|
+
#private;
|
|
88
|
+
/** the declaration as published — a copy; mutating it changes nothing
|
|
89
|
+
* (port-review-2 M-3: the validated state must not be reachable from
|
|
90
|
+
* outside the validated paths). */
|
|
91
|
+
get decl(): CarrierDeclaration;
|
|
92
|
+
private policy;
|
|
93
|
+
private events;
|
|
94
|
+
private bindings;
|
|
95
|
+
private tombstones;
|
|
96
|
+
private releaseSeq;
|
|
97
|
+
private challenges;
|
|
98
|
+
private clock;
|
|
99
|
+
constructor(decl: CarrierDeclaration, policy?: CarrierPolicy, events?: CarrierEvents);
|
|
100
|
+
private advance;
|
|
101
|
+
tick(now: number): void;
|
|
102
|
+
/** The gated challenge entry — guarantee 3 BY CONSTRUCTION
|
|
103
|
+
* (port-review-3 M-3): the admission gate runs INSIDE, before any
|
|
104
|
+
* entropy is drawn, so a refused request costs neither randomness nor
|
|
105
|
+
* sealing. `draw` is invoked only past the gate; its `addressValue`
|
|
106
|
+
* (for registration challenges) is the value the adapter will seal to
|
|
107
|
+
* the rkid — the carrier remembers it and a proof must return exactly
|
|
108
|
+
* it. Every challenge is BOUND to its rkid (port-review-3 B-1: a
|
|
109
|
+
* null-rkid challenge disabled the address proof).
|
|
110
|
+
* Returns null when the gate refuses — retriable, guarantee 2. */
|
|
111
|
+
issueChallenge(now: number, rkid: string, draw: () => {
|
|
112
|
+
entropy: Uint8Array;
|
|
113
|
+
addressValue?: string;
|
|
114
|
+
}): string | null;
|
|
115
|
+
/** consume-first (§5a.3): the first attempt takes the challenge before
|
|
116
|
+
* anything is verified; expiry and rkid binding are checked HERE, so a
|
|
117
|
+
* stale or transplanted challenge dies without buying a verification. */
|
|
118
|
+
private consume;
|
|
119
|
+
register(proof: CarrierProof, opts: {
|
|
120
|
+
now: number;
|
|
121
|
+
rawGeneration: string;
|
|
122
|
+
}): Promise<RegistrationVerdict>;
|
|
123
|
+
private freshBinding;
|
|
124
|
+
private reopen;
|
|
125
|
+
collect(proof: CarrierProof, opts: {
|
|
126
|
+
now: number;
|
|
127
|
+
}): Promise<SessionVerdict & {
|
|
128
|
+
deposits?: Array<{
|
|
129
|
+
bytes: Uint8Array;
|
|
130
|
+
digest: string;
|
|
131
|
+
}>;
|
|
132
|
+
}>;
|
|
133
|
+
conclude(proof: CarrierProof, digest: string, opts: {
|
|
134
|
+
now: number;
|
|
135
|
+
}): Promise<SessionVerdict>;
|
|
136
|
+
private session;
|
|
137
|
+
submit(rkid: string, callerBytes: Uint8Array, opts: {
|
|
138
|
+
now: number;
|
|
139
|
+
}): Promise<SubmissionVerdict>;
|
|
140
|
+
private pendingSeqInstant;
|
|
141
|
+
private installTombstone;
|
|
142
|
+
private trimTombstones;
|
|
143
|
+
/** guarantee 1: the declaration binds, and a revision is itself
|
|
144
|
+
* validated; a lowered tombstone bound trims in the same step
|
|
145
|
+
* (round-45 B-3 — standing state is not a running act). */
|
|
146
|
+
reviseDeclaration(next: Partial<CarrierDeclaration>): void;
|
|
147
|
+
stateOf(rkid: string): 'unbound' | 'live' | 'closing' | 'released';
|
|
148
|
+
tombstoneOf(rkid: string): number | null;
|
|
149
|
+
bindingOf(rkid: string): {
|
|
150
|
+
generation: number;
|
|
151
|
+
principal: string;
|
|
152
|
+
deposits: number;
|
|
153
|
+
deadline?: number;
|
|
154
|
+
} | null;
|
|
155
|
+
tombstoneLabels(): string[];
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=carrier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"carrier.d.ts","sourceRoot":"","sources":["../src/carrier.ts"],"names":[],"mappings":"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"}
|