@serve.zone/interfaces 31.6.0 → 31.8.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 +47 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/data/index.d.ts +1 -0
- package/dist_ts/data/index.js +2 -1
- package/dist_ts/data/networkcredential.d.ts +10 -4
- package/dist_ts/data/networkcredential.js +14 -8
- package/dist_ts/data/networkdelivery.d.ts +21 -0
- package/dist_ts/data/networkdelivery.js +35 -7
- package/dist_ts/data/networklease.d.ts +110 -0
- package/dist_ts/data/networklease.js +159 -0
- package/dist_ts/data/networkprojection.d.ts +10 -5
- package/dist_ts/data/networkprojection.js +15 -22
- package/dist_ts/data/networksigning.js +5 -4
- package/dist_ts/private/networkcontract.d.ts +16 -0
- package/dist_ts/private/networkcontract.js +31 -1
- package/dist_ts/requests/cluster.d.ts +16 -0
- package/dist_ts/requests/cluster.js +1 -1
- package/dist_ts/requests/node.d.ts +31 -0
- package/dist_ts/requests/runtimesession.d.ts +14 -0
- package/dist_ts/runtime.networkprojection.d.ts +14 -0
- package/dist_ts/runtime.networkprojection.js +68 -19
- package/package.json +2 -2
- package/readme.md +144 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/data/index.ts +1 -0
- package/ts/data/networkcredential.ts +19 -9
- package/ts/data/networkdelivery.ts +49 -6
- package/ts/data/networklease.ts +229 -0
- package/ts/data/networkprojection.ts +28 -26
- package/ts/data/networksigning.ts +5 -4
- package/ts/private/networkcontract.ts +34 -0
- package/ts/requests/cluster.ts +20 -0
- package/ts/requests/node.ts +35 -0
- package/ts/requests/runtimesession.ts +17 -0
- package/ts/runtime.networkprojection.ts +87 -20
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import * as plugins from './plugins.runtime.js';
|
|
2
|
-
import type { IRuntimeAuthorityReferenceV1 } from './data/runtimeassignment.js';
|
|
2
|
+
import type { IRuntimeAuthorityReferenceV1, IRuntimeControllerV1 } from './data/runtimeassignment.js';
|
|
3
3
|
import type { IRuntimeNetworkProjectionV1 } from './data/networkprojection.js';
|
|
4
4
|
import { snapshotRuntimeNetworkNodeScopeV1, snapshotRuntimeNetworkProjectionV1, validateRuntimeNetworkProjectionV1 } from './data/networkprojection.js';
|
|
5
5
|
import type { IRuntimeNetworkSigningAuthorityV1, ISignedRuntimeNetworkProjectionV1 } from './data/networksigning.js';
|
|
6
6
|
import { computeRuntimeNetworkSigningAuthorityV1Digest, runtimeNetworkSigningV1Contract,
|
|
7
7
|
snapshotRuntimeNetworkSigningAuthorityV1, snapshotSignedRuntimeNetworkProjectionV1 } from './data/networksigning.js';
|
|
8
|
-
import {
|
|
8
|
+
import type { IRuntimeNetworkDnsLeaseRenewal, ISignedRuntimeNetworkDnsLeaseRenewal } from './data/networklease.js';
|
|
9
|
+
import { runtimeNetworkDnsLeaseRenewalContract, snapshotRuntimeNetworkDnsLeaseRenewal,
|
|
10
|
+
snapshotSignedRuntimeNetworkDnsLeaseRenewal, validateRuntimeNetworkDnsLeaseRenewal } from './data/networklease.js';
|
|
11
|
+
import { captureNetwork, failNetwork, networkCanonical, networkEqual, networkReference, networkReferenceOf,
|
|
12
|
+
networkSameScope, requireNetwork } from './private/networkcontract.js';
|
|
9
13
|
|
|
10
14
|
/** The private KeyObject is process-local. Persist only through the controller's encrypted secret store. */
|
|
11
15
|
export const createRuntimeNetworkSigningKeyV1 = (): { publicKey: string; privateKey: plugins.crypto.KeyObject } => {
|
|
@@ -15,11 +19,47 @@ export const createRuntimeNetworkSigningKeyV1 = (): { publicKey: string; private
|
|
|
15
19
|
return { publicKey: Buffer.from(jwk.x, 'base64url').toString('hex'), privateKey: pair.privateKey };
|
|
16
20
|
};
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
/** What every signed network statement carries besides its content. */
|
|
23
|
+
interface IAuthoritySignature {
|
|
24
|
+
authority: IRuntimeAuthorityReferenceV1;
|
|
25
|
+
signature: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const projectionEnvelope = (authority: IRuntimeAuthorityReferenceV1, projection: IRuntimeNetworkProjectionV1) =>
|
|
29
|
+
({ domain: runtimeNetworkSigningV1Contract.signatureDomain, schemaVersion: 1, authority, projection });
|
|
30
|
+
const renewalEnvelope = (authority: IRuntimeAuthorityReferenceV1, renewal: IRuntimeNetworkDnsLeaseRenewal) =>
|
|
31
|
+
({ domain: runtimeNetworkDnsLeaseRenewalContract.signatureDomain, authority, renewal });
|
|
32
|
+
const envelopeBytes = (envelope: object): Uint8Array => new TextEncoder().encode(networkCanonical(envelope));
|
|
33
|
+
|
|
34
|
+
/** A revoked revision has no key; any other must be intact and belong to the controller that owns the content. */
|
|
35
|
+
const liveKeyOf = async (authority: IRuntimeNetworkSigningAuthorityV1, contentController: IRuntimeControllerV1): Promise<string> => {
|
|
36
|
+
const { publicKey } = authority;
|
|
37
|
+
requireNetwork(publicKey !== null && networkEqual(authority.controller, contentController)
|
|
22
38
|
&& authority.digest === await computeRuntimeNetworkSigningAuthorityV1Digest(authority));
|
|
39
|
+
return publicKey;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/** Sign as the authority's revision, and only with the private half of its live key. */
|
|
43
|
+
const signAs = async (
|
|
44
|
+
authority: IRuntimeNetworkSigningAuthorityV1, privateKey: plugins.crypto.KeyObject, contentController: IRuntimeControllerV1,
|
|
45
|
+
envelopeOf: (reference: IRuntimeAuthorityReferenceV1) => object,
|
|
46
|
+
): Promise<IAuthoritySignature> => {
|
|
47
|
+
requireNetwork(privateKey instanceof plugins.crypto.KeyObject && privateKey.type === 'private' && privateKey.asymmetricKeyType === 'ed25519');
|
|
48
|
+
const derived = plugins.crypto.createPublicKey(privateKey).export({ format: 'jwk' });
|
|
49
|
+
const publicKey = await liveKeyOf(authority, contentController);
|
|
50
|
+
requireNetwork(typeof derived.x === 'string' && Buffer.from(derived.x, 'base64url').toString('hex') === publicKey);
|
|
51
|
+
const reference = networkReferenceOf(authority);
|
|
52
|
+
return { authority: reference, signature: plugins.crypto.sign(null, envelopeBytes(envelopeOf(reference)), privateKey).toString('hex') };
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/** The receiver's own trusted revision decides; the envelope only names which revision it claims. */
|
|
56
|
+
const requireSignedBy = async (
|
|
57
|
+
trusted: IRuntimeNetworkSigningAuthorityV1, signed: IAuthoritySignature, contentController: IRuntimeControllerV1, envelope: object,
|
|
58
|
+
): Promise<void> => {
|
|
59
|
+
requireNetwork(networkEqual(signed.authority, networkReferenceOf(trusted)));
|
|
60
|
+
const key = plugins.crypto.createPublicKey({ format: 'jwk', key: { kty: 'OKP', crv: 'Ed25519',
|
|
61
|
+
x: Buffer.from(await liveKeyOf(trusted, contentController), 'hex').toString('base64url') } });
|
|
62
|
+
requireNetwork(plugins.crypto.verify(null, envelopeBytes(envelope), key, Buffer.from(signed.signature, 'hex')));
|
|
23
63
|
};
|
|
24
64
|
|
|
25
65
|
/** Sign only validated complete state and a matching dedicated private key. */
|
|
@@ -28,14 +68,9 @@ export const signRuntimeNetworkProjectionV1 = async (
|
|
|
28
68
|
): Promise<ISignedRuntimeNetworkProjectionV1> => {
|
|
29
69
|
try {
|
|
30
70
|
const input = snapshotRuntimeNetworkProjectionV1(projectionValue), authority = snapshotRuntimeNetworkSigningAuthorityV1(authorityValue);
|
|
31
|
-
requireNetwork(privateKey instanceof plugins.crypto.KeyObject && privateKey.type === 'private' && privateKey.asymmetricKeyType === 'ed25519');
|
|
32
|
-
const publicKey = plugins.crypto.createPublicKey(privateKey).export({ format: 'jwk' });
|
|
33
|
-
requireNetwork(typeof publicKey.x === 'string' && Buffer.from(publicKey.x, 'base64url').toString('hex') === authority.publicKey);
|
|
34
71
|
const projection = await validateRuntimeNetworkProjectionV1(input);
|
|
35
|
-
await
|
|
36
|
-
|
|
37
|
-
const signature = plugins.crypto.sign(null, signatureBytes(reference, projection), privateKey).toString('hex');
|
|
38
|
-
return { schemaVersion: 1, authority: reference, projection, signature };
|
|
72
|
+
const signed = await signAs(authority, privateKey, projection.controller, reference => projectionEnvelope(reference, projection));
|
|
73
|
+
return { schemaVersion: 1, authority: signed.authority, projection, signature: signed.signature };
|
|
39
74
|
} catch { return failNetwork(); }
|
|
40
75
|
};
|
|
41
76
|
|
|
@@ -51,14 +86,46 @@ export const verifyRuntimeNetworkProjectionV1 = async (
|
|
|
51
86
|
const signed = snapshotSignedRuntimeNetworkProjectionV1(value);
|
|
52
87
|
const authority = snapshotRuntimeNetworkSigningAuthorityV1(trustedAuthorityValue);
|
|
53
88
|
const trusted = snapshotRuntimeNetworkNodeScopeV1(trustedScopeValue);
|
|
54
|
-
requireNetwork(
|
|
55
|
-
|
|
56
|
-
&& networkEqual(signed.projection.controller, trusted.controller));
|
|
57
|
-
await validateAuthority(authority, signed.projection);
|
|
58
|
-
const key = plugins.crypto.createPublicKey({ format: 'jwk', key: { kty: 'OKP', crv: 'Ed25519',
|
|
59
|
-
x: Buffer.from(authority.publicKey!, 'hex').toString('base64url') } });
|
|
60
|
-
requireNetwork(plugins.crypto.verify(null, signatureBytes(signed.authority, signed.projection), key, Buffer.from(signed.signature, 'hex')));
|
|
89
|
+
requireNetwork(networkSameScope(signed.projection, trusted));
|
|
90
|
+
await requireSignedBy(authority, signed, signed.projection.controller, projectionEnvelope(signed.authority, signed.projection));
|
|
61
91
|
await validateRuntimeNetworkProjectionV1(signed.projection);
|
|
62
92
|
return signed;
|
|
63
93
|
} catch { return failNetwork(); }
|
|
64
94
|
};
|
|
95
|
+
|
|
96
|
+
/** Sign only a validated renewal, with the same authority and key that sign this controller's projections. */
|
|
97
|
+
export const signRuntimeNetworkDnsLeaseRenewal = async (
|
|
98
|
+
renewalValue: unknown, authorityValue: unknown, privateKey: plugins.crypto.KeyObject,
|
|
99
|
+
): Promise<ISignedRuntimeNetworkDnsLeaseRenewal> => {
|
|
100
|
+
try {
|
|
101
|
+
const input = snapshotRuntimeNetworkDnsLeaseRenewal(renewalValue), authority = snapshotRuntimeNetworkSigningAuthorityV1(authorityValue);
|
|
102
|
+
const renewal = await validateRuntimeNetworkDnsLeaseRenewal(input);
|
|
103
|
+
const signed = await signAs(authority, privateKey, renewal.controller, reference => renewalEnvelope(reference, renewal));
|
|
104
|
+
return { authority: signed.authority, renewal, signature: signed.signature };
|
|
105
|
+
} catch { return failNetwork(); }
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* trustedAuthorityValue is receiver-owned persisted trust, NEVER envelope material, and a relay
|
|
110
|
+
* that delivers the renewal adds no trust to it. projectionAuthorityValue is the authority
|
|
111
|
+
* reference that signed the projection this renewal extends, which the receiver kept when it
|
|
112
|
+
* admitted that projection: a renewal is only ever valid under the exact revision that signed its
|
|
113
|
+
* projection, so a rotated key renews nothing and DNS still waits for a newly signed projection.
|
|
114
|
+
* This verifies content, scope and signature only: the owner still admits it against its own
|
|
115
|
+
* admitted projection with `admitRuntimeNetworkDnsLeaseRenewal`, fences the live session and
|
|
116
|
+
* converts the window with a qualified clock.
|
|
117
|
+
*/
|
|
118
|
+
export const verifyRuntimeNetworkDnsLeaseRenewal = async (
|
|
119
|
+
value: unknown, trustedAuthorityValue: unknown, trustedScopeValue: unknown, projectionAuthorityValue: unknown,
|
|
120
|
+
): Promise<ISignedRuntimeNetworkDnsLeaseRenewal> => {
|
|
121
|
+
try {
|
|
122
|
+
const signed = snapshotSignedRuntimeNetworkDnsLeaseRenewal(value);
|
|
123
|
+
const authority = snapshotRuntimeNetworkSigningAuthorityV1(trustedAuthorityValue);
|
|
124
|
+
const trusted = snapshotRuntimeNetworkNodeScopeV1(trustedScopeValue);
|
|
125
|
+
const projectionAuthority = networkReference(captureNetwork(projectionAuthorityValue));
|
|
126
|
+
requireNetwork(networkSameScope(signed.renewal, trusted) && networkEqual(signed.authority, projectionAuthority));
|
|
127
|
+
await requireSignedBy(authority, signed, signed.renewal.controller, renewalEnvelope(signed.authority, signed.renewal));
|
|
128
|
+
await validateRuntimeNetworkDnsLeaseRenewal(signed.renewal);
|
|
129
|
+
return signed;
|
|
130
|
+
} catch { return failNetwork(); }
|
|
131
|
+
};
|