@serve.zone/interfaces 30.11.0 → 30.12.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 +6 -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 +32 -0
- package/dist_ts/data/networkcredential.js +66 -0
- package/dist_ts/requests/runtimesession.d.ts +7 -0
- package/package.json +1 -1
- package/readme.md +25 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/data/index.ts +1 -0
- package/ts/data/networkcredential.ts +88 -0
- package/ts/requests/runtimesession.ts +10 -0
package/changelog.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026-09-15 - 30.12.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- Add exact session and projection bound managed VPN credential contracts with selected UDP relay, canonical key encoding and bounded lease validation.
|
|
8
|
+
|
|
3
9
|
## 2026-09-14 - 30.11.0
|
|
4
10
|
|
|
5
11
|
### Features
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/interfaces',
|
|
6
|
-
version: '30.
|
|
6
|
+
version: '30.12.0',
|
|
7
7
|
description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFNBQVM7SUFDbEIsV0FBVyxFQUFFLHVGQUF1RjtDQUNyRyxDQUFBIn0=
|
package/dist_ts/data/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export * from './mail.js';
|
|
|
23
23
|
export * from './nodecredential.js';
|
|
24
24
|
export * from './nodeenrollment.js';
|
|
25
25
|
export * from './networkauthority.js';
|
|
26
|
+
export * from './networkcredential.js';
|
|
26
27
|
export * from './networkdelivery.js';
|
|
27
28
|
export * from './networkprojection.js';
|
|
28
29
|
export type { IRuntimeNetworkRouterPacketGrantV1, IRuntimeNetworkRouterProjectionV1 } from './networkrouter.js';
|
package/dist_ts/data/index.js
CHANGED
|
@@ -23,6 +23,7 @@ export * from './mail.js';
|
|
|
23
23
|
export * from './nodecredential.js';
|
|
24
24
|
export * from './nodeenrollment.js';
|
|
25
25
|
export * from './networkauthority.js';
|
|
26
|
+
export * from './networkcredential.js';
|
|
26
27
|
export * from './networkdelivery.js';
|
|
27
28
|
export * from './networkprojection.js';
|
|
28
29
|
export * from './networkprotection.js';
|
|
@@ -49,4 +50,4 @@ export * from './traffic.js';
|
|
|
49
50
|
export * from './user.js';
|
|
50
51
|
export * from './version.js';
|
|
51
52
|
export * from './webpush.js';
|
|
52
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxlQUFlLENBQUM7QUFDOUIsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMseUJBQXlCLENBQUM7QUFDeEMsY0FBYywwQkFBMEIsQ0FBQztBQUN6QyxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxVQUFVLENBQUM7QUFDekIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxZQUFZLENBQUM7QUFDM0IsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLGdCQUFnQixDQUFDO0FBQy9CLGNBQWMsWUFBWSxDQUFDO0FBQzNCLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsV0FBVyxDQUFDO0FBQzFCLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLHdCQUF3QixDQUFDO0FBRXZDLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxvQkFBb0IsQ0FBQztBQUNuQyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsNkJBQTZCLENBQUM7QUFDNUMsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMsc0JBQXNCLENBQUM7QUFDckMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLG1CQUFtQixDQUFDO0FBQ2xDLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxXQUFXLENBQUM7QUFDMUIsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxjQUFjLENBQUMifQ==
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { IRuntimeAuthorityReferenceV1 } from './runtimeassignment.js';
|
|
2
|
+
import { type IRuntimeSessionBindingV1 } from './runtimesession.js';
|
|
3
|
+
export interface IGetRuntimeManagedVpnCredentialRequestV1 {
|
|
4
|
+
session: IRuntimeSessionBindingV1;
|
|
5
|
+
projection: IRuntimeAuthorityReferenceV1;
|
|
6
|
+
}
|
|
7
|
+
/** Secret response over the current authenticated physical peer only. Never
|
|
8
|
+
* persist, hash, log, or include it in a signed network projection. The native
|
|
9
|
+
* Noise owner validates and uses the keys; these shapes confer no TUN readiness. */
|
|
10
|
+
export interface IGetRuntimeManagedVpnCredentialResponseV1 extends IGetRuntimeManagedVpnCredentialRequestV1 {
|
|
11
|
+
transport: 'quic';
|
|
12
|
+
relay: {
|
|
13
|
+
id: string;
|
|
14
|
+
address: string;
|
|
15
|
+
port: number;
|
|
16
|
+
};
|
|
17
|
+
authorityId: string;
|
|
18
|
+
serverPublicKey: string;
|
|
19
|
+
clientPublicKey: string;
|
|
20
|
+
clientPrivateKey: string;
|
|
21
|
+
/** Unix milliseconds; cannot outlive the referenced projection's DNS lease. */
|
|
22
|
+
expiresAt: number;
|
|
23
|
+
}
|
|
24
|
+
export declare const snapshotGetRuntimeManagedVpnCredentialRequestV1: (value: unknown) => IGetRuntimeManagedVpnCredentialRequestV1;
|
|
25
|
+
export declare const snapshotGetRuntimeManagedVpnCredentialResponseV1: (value: unknown) => IGetRuntimeManagedVpnCredentialResponseV1;
|
|
26
|
+
/** Content binding only. The caller must resolve the exact current projection
|
|
27
|
+
* and authenticate/fence the current physical peer before and after native work. */
|
|
28
|
+
export declare const bindGetRuntimeManagedVpnCredentialRequestV1: (value: unknown, projectionValue: unknown, trustedSessionValue: unknown) => Promise<IGetRuntimeManagedVpnCredentialRequestV1>;
|
|
29
|
+
/** Bind the secret response to the original request and exact selected router
|
|
30
|
+
* UDP endpoint. Time is caller-qualified; this helper does not sample a clock,
|
|
31
|
+
* authenticate a transport, admit policy or prove a running managed connection. */
|
|
32
|
+
export declare const bindGetRuntimeManagedVpnCredentialResponseV1: (value: unknown, requestValue: unknown, projectionValue: unknown, trustedSessionValue: unknown, nowValue: unknown) => Promise<IGetRuntimeManagedVpnCredentialResponseV1>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { snapshotRuntimeSessionBindingV1 } from './runtimesession.js';
|
|
2
|
+
import { validateRuntimeNetworkProjectionV1 } from './networkprojection.js';
|
|
3
|
+
import { captureNetwork, failNetwork, networkCounter, networkEqual, networkId, networkIpv4, networkRecord, networkReference, networkReferenceOf, networkSafe, requireNetwork } from '../private/networkcontract.js';
|
|
4
|
+
/** Canonical 32-byte key encoding only. Cryptographic key agreement and pair
|
|
5
|
+
* validation belong to the native Noise implementation, not this JSON parser. */
|
|
6
|
+
const key = (value) => {
|
|
7
|
+
requireNetwork(typeof value === 'string' && /^[A-Za-z0-9+/]{43}=$/.test(value));
|
|
8
|
+
const decoded = atob(value);
|
|
9
|
+
requireNetwork(decoded.length === 32 && btoa(decoded) === value && [...decoded].some(byte => byte.charCodeAt(0) !== 0));
|
|
10
|
+
return value;
|
|
11
|
+
};
|
|
12
|
+
export const snapshotGetRuntimeManagedVpnCredentialRequestV1 = (value) => networkSafe(() => {
|
|
13
|
+
const item = networkRecord(captureNetwork(value), ['session', 'projection']);
|
|
14
|
+
return { session: snapshotRuntimeSessionBindingV1(item.session), projection: networkReference(item.projection) };
|
|
15
|
+
});
|
|
16
|
+
export const snapshotGetRuntimeManagedVpnCredentialResponseV1 = (value) => networkSafe(() => {
|
|
17
|
+
const item = networkRecord(captureNetwork(value), ['session', 'projection', 'transport', 'relay', 'authorityId',
|
|
18
|
+
'serverPublicKey', 'clientPublicKey', 'clientPrivateKey', 'expiresAt']);
|
|
19
|
+
const relay = networkRecord(item.relay, ['id', 'address', 'port']);
|
|
20
|
+
requireNetwork(item.transport === 'quic');
|
|
21
|
+
return { session: snapshotRuntimeSessionBindingV1(item.session), projection: networkReference(item.projection), transport: 'quic',
|
|
22
|
+
relay: { id: networkId(relay.id), address: networkIpv4(relay.address), port: networkCounter(relay.port, 65535) },
|
|
23
|
+
authorityId: networkId(item.authorityId), serverPublicKey: key(item.serverPublicKey), clientPublicKey: key(item.clientPublicKey),
|
|
24
|
+
clientPrivateKey: key(item.clientPrivateKey), expiresAt: networkCounter(item.expiresAt) };
|
|
25
|
+
});
|
|
26
|
+
const bindRequest = (request, projection, trusted) => {
|
|
27
|
+
requireNetwork(networkEqual(request.session, trusted) && networkEqual(request.projection, networkReferenceOf(projection))
|
|
28
|
+
&& networkEqual(projection.controller, trusted.controller) && projection.nodeId === trusted.nodeId
|
|
29
|
+
&& projection.runtimeNamespace === trusted.runtimeNamespace && projection.handoff);
|
|
30
|
+
};
|
|
31
|
+
/** Content binding only. The caller must resolve the exact current projection
|
|
32
|
+
* and authenticate/fence the current physical peer before and after native work. */
|
|
33
|
+
export const bindGetRuntimeManagedVpnCredentialRequestV1 = async (value, projectionValue, trustedSessionValue) => {
|
|
34
|
+
try {
|
|
35
|
+
const request = snapshotGetRuntimeManagedVpnCredentialRequestV1(value);
|
|
36
|
+
const trusted = snapshotRuntimeSessionBindingV1(trustedSessionValue);
|
|
37
|
+
const projection = await validateRuntimeNetworkProjectionV1(projectionValue);
|
|
38
|
+
bindRequest(request, projection, trusted);
|
|
39
|
+
return request;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return failNetwork();
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
/** Bind the secret response to the original request and exact selected router
|
|
46
|
+
* UDP endpoint. Time is caller-qualified; this helper does not sample a clock,
|
|
47
|
+
* authenticate a transport, admit policy or prove a running managed connection. */
|
|
48
|
+
export const bindGetRuntimeManagedVpnCredentialResponseV1 = async (value, requestValue, projectionValue, trustedSessionValue, nowValue) => {
|
|
49
|
+
try {
|
|
50
|
+
const response = snapshotGetRuntimeManagedVpnCredentialResponseV1(value);
|
|
51
|
+
const request = snapshotGetRuntimeManagedVpnCredentialRequestV1(requestValue);
|
|
52
|
+
const trusted = snapshotRuntimeSessionBindingV1(trustedSessionValue), now = networkCounter(nowValue);
|
|
53
|
+
const projection = await validateRuntimeNetworkProjectionV1(projectionValue);
|
|
54
|
+
bindRequest(request, projection, trusted);
|
|
55
|
+
requireNetwork(networkEqual(response.session, request.session) && networkEqual(response.projection, request.projection));
|
|
56
|
+
requireNetwork(projection.router?.platformEndpointIds.includes(response.relay.id));
|
|
57
|
+
const endpoint = projection.protectedAuthority.platformEndpoints.find(item => item.id === response.relay.id);
|
|
58
|
+
requireNetwork(endpoint && endpoint.protocol === 'udp' && endpoint.address === response.relay.address && endpoint.port === response.relay.port);
|
|
59
|
+
requireNetwork(projection.dns.notBefore <= now && now < response.expiresAt && response.expiresAt <= projection.dns.expiresAt);
|
|
60
|
+
return response;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return failNetwork();
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29ya2NyZWRlbnRpYWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL25ldHdvcmtjcmVkZW50aWFsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSwrQkFBK0IsRUFBaUMsTUFBTSxxQkFBcUIsQ0FBQztBQUNyRyxPQUFPLEVBQUUsa0NBQWtDLEVBQW9DLE1BQU0sd0JBQXdCLENBQUM7QUFDOUcsT0FBTyxFQUFFLGNBQWMsRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUN4RixhQUFhLEVBQUUsZ0JBQWdCLEVBQUUsa0JBQWtCLEVBQUUsV0FBVyxFQUFFLGNBQWMsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBcUIxSDtpRkFDaUY7QUFDakYsTUFBTSxHQUFHLEdBQUcsQ0FBQyxLQUFjLEVBQVUsRUFBRTtJQUNyQyxjQUFjLENBQUMsT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLHNCQUFzQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ2hGLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM1QixjQUFjLENBQUMsT0FBTyxDQUFDLE1BQU0sS0FBSyxFQUFFLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEtBQUssSUFBSSxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hILE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sK0NBQStDLEdBQUcsQ0FBQyxLQUFjLEVBQTRDLEVBQUUsQ0FBQyxXQUFXLENBQUMsR0FBRyxFQUFFO0lBQzVJLE1BQU0sSUFBSSxHQUFHLGFBQWEsQ0FBQyxjQUFjLENBQUMs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
|
|
@@ -3,6 +3,13 @@ import type * as data from '../data/runtimesession.js';
|
|
|
3
3
|
import type * as terminal from '../data/runtimeterminalreceipt.js';
|
|
4
4
|
import type * as network from '../data/networkdelivery.js';
|
|
5
5
|
import type * as protection from '../data/networkprotection.js';
|
|
6
|
+
import type * as credential from '../data/networkcredential.js';
|
|
7
|
+
/** Current-peer, exact-projection authorization; response contains secret keys. */
|
|
8
|
+
export interface IReq_Pallet_Controller_GetRuntimeManagedVpnCredentialV1 extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Pallet_Controller_GetRuntimeManagedVpnCredentialV1> {
|
|
9
|
+
method: 'getRuntimeManagedVpnCredentialV1';
|
|
10
|
+
request: credential.IGetRuntimeManagedVpnCredentialRequestV1;
|
|
11
|
+
response: credential.IGetRuntimeManagedVpnCredentialResponseV1;
|
|
12
|
+
}
|
|
6
13
|
/** Current authenticated peer reports its durable complete native protection journal. */
|
|
7
14
|
export interface IReq_Pallet_Controller_ReportRuntimeNetworkProtectionV1 extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Pallet_Controller_ReportRuntimeNetworkProtectionV1> {
|
|
8
15
|
method: 'reportRuntimeNetworkProtectionV1';
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -415,6 +415,31 @@ exported material only through its encrypted internal secret store. The dedicate
|
|
|
415
415
|
peer. Their response acknowledges durable admission only, never application,
|
|
416
416
|
readiness, independent fencing or pool activation.
|
|
417
417
|
|
|
418
|
+
The `getRuntimeManagedVpnCredentialV1` method contract in `requests.runtimesession`
|
|
419
|
+
uses `IGetRuntimeManagedVpnCredentialRequestV1` and
|
|
420
|
+
`IGetRuntimeManagedVpnCredentialResponseV1`. Its request carries the exact current
|
|
421
|
+
session and signed projection reference. The secret response repeats those
|
|
422
|
+
bindings and supplies a QUIC relay tuple, managed authority ID, Noise server
|
|
423
|
+
public key, client keypair and expiry in Unix milliseconds. Keep the response
|
|
424
|
+
process-local; never persist, hash, log or embed it in a signed projection.
|
|
425
|
+
|
|
426
|
+
`snapshotGetRuntimeManagedVpnCredentialRequestV1` and its response counterpart
|
|
427
|
+
capture closed detached JSON shapes and canonical 32-byte key encodings.
|
|
428
|
+
`bindGetRuntimeManagedVpnCredentialRequestV1(request, projection, trustedSession)`
|
|
429
|
+
validates the complete projection digest and binds node, controller, namespace,
|
|
430
|
+
physical-session identity and projection reference. The response binder takes
|
|
431
|
+
`(response, request, projection, trustedSession, now)` and additionally requires
|
|
432
|
+
the relay's exact UDP tuple to be selected in `router.platformEndpointIds`.
|
|
433
|
+
Expiry must be after the caller-qualified time and no later than the referenced
|
|
434
|
+
projection's DNS lease; acceptance before that lease starts rejects.
|
|
435
|
+
|
|
436
|
+
These helpers perform content validation. Callers authenticate and fence the
|
|
437
|
+
current physical peer and projection before and after native work, qualify time
|
|
438
|
+
independently, and retain ownership through revocation and shutdown. The native
|
|
439
|
+
Noise implementation owns cryptographic validation and authentication. Credential
|
|
440
|
+
delivery does not prove a connected VPN, TUN ownership, packet enforcement or
|
|
441
|
+
workload readiness, and does not replace explicit packet withdrawals.
|
|
442
|
+
|
|
418
443
|
### Node-Bound Runtime Assignments
|
|
419
444
|
|
|
420
445
|
The `data` namespace exports `IRuntimeAssignmentV1`, canonical digest helpers,
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/data/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ export * from './mail.js';
|
|
|
23
23
|
export * from './nodecredential.js';
|
|
24
24
|
export * from './nodeenrollment.js';
|
|
25
25
|
export * from './networkauthority.js';
|
|
26
|
+
export * from './networkcredential.js';
|
|
26
27
|
export * from './networkdelivery.js';
|
|
27
28
|
export * from './networkprojection.js';
|
|
28
29
|
export type { IRuntimeNetworkRouterPacketGrantV1, IRuntimeNetworkRouterProjectionV1 } from './networkrouter.js';
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { IRuntimeAuthorityReferenceV1 } from './runtimeassignment.js';
|
|
2
|
+
import { snapshotRuntimeSessionBindingV1, type IRuntimeSessionBindingV1 } from './runtimesession.js';
|
|
3
|
+
import { validateRuntimeNetworkProjectionV1, type IRuntimeNetworkProjectionV1 } from './networkprojection.js';
|
|
4
|
+
import { captureNetwork, failNetwork, networkCounter, networkEqual, networkId, networkIpv4,
|
|
5
|
+
networkRecord, networkReference, networkReferenceOf, networkSafe, requireNetwork } from '../private/networkcontract.js';
|
|
6
|
+
|
|
7
|
+
export interface IGetRuntimeManagedVpnCredentialRequestV1 {
|
|
8
|
+
session: IRuntimeSessionBindingV1;
|
|
9
|
+
projection: IRuntimeAuthorityReferenceV1;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Secret response over the current authenticated physical peer only. Never
|
|
13
|
+
* persist, hash, log, or include it in a signed network projection. The native
|
|
14
|
+
* Noise owner validates and uses the keys; these shapes confer no TUN readiness. */
|
|
15
|
+
export interface IGetRuntimeManagedVpnCredentialResponseV1 extends IGetRuntimeManagedVpnCredentialRequestV1 {
|
|
16
|
+
transport: 'quic';
|
|
17
|
+
relay: { id: string; address: string; port: number };
|
|
18
|
+
authorityId: string;
|
|
19
|
+
serverPublicKey: string;
|
|
20
|
+
clientPublicKey: string;
|
|
21
|
+
clientPrivateKey: string;
|
|
22
|
+
/** Unix milliseconds; cannot outlive the referenced projection's DNS lease. */
|
|
23
|
+
expiresAt: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Canonical 32-byte key encoding only. Cryptographic key agreement and pair
|
|
27
|
+
* validation belong to the native Noise implementation, not this JSON parser. */
|
|
28
|
+
const key = (value: unknown): string => {
|
|
29
|
+
requireNetwork(typeof value === 'string' && /^[A-Za-z0-9+/]{43}=$/.test(value));
|
|
30
|
+
const decoded = atob(value);
|
|
31
|
+
requireNetwork(decoded.length === 32 && btoa(decoded) === value && [...decoded].some(byte => byte.charCodeAt(0) !== 0));
|
|
32
|
+
return value;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const snapshotGetRuntimeManagedVpnCredentialRequestV1 = (value: unknown): IGetRuntimeManagedVpnCredentialRequestV1 => networkSafe(() => {
|
|
36
|
+
const item = networkRecord(captureNetwork(value), ['session', 'projection']);
|
|
37
|
+
return { session: snapshotRuntimeSessionBindingV1(item.session), projection: networkReference(item.projection) };
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export const snapshotGetRuntimeManagedVpnCredentialResponseV1 = (value: unknown): IGetRuntimeManagedVpnCredentialResponseV1 => networkSafe(() => {
|
|
41
|
+
const item = networkRecord(captureNetwork(value), ['session', 'projection', 'transport', 'relay', 'authorityId',
|
|
42
|
+
'serverPublicKey', 'clientPublicKey', 'clientPrivateKey', 'expiresAt']);
|
|
43
|
+
const relay = networkRecord(item.relay, ['id', 'address', 'port']); requireNetwork(item.transport === 'quic');
|
|
44
|
+
return { session: snapshotRuntimeSessionBindingV1(item.session), projection: networkReference(item.projection), transport: 'quic',
|
|
45
|
+
relay: { id: networkId(relay.id), address: networkIpv4(relay.address), port: networkCounter(relay.port, 65535) },
|
|
46
|
+
authorityId: networkId(item.authorityId), serverPublicKey: key(item.serverPublicKey), clientPublicKey: key(item.clientPublicKey),
|
|
47
|
+
clientPrivateKey: key(item.clientPrivateKey), expiresAt: networkCounter(item.expiresAt) };
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const bindRequest = (request: IGetRuntimeManagedVpnCredentialRequestV1,
|
|
51
|
+
projection: IRuntimeNetworkProjectionV1, trusted: IRuntimeSessionBindingV1): void => {
|
|
52
|
+
requireNetwork(networkEqual(request.session, trusted) && networkEqual(request.projection, networkReferenceOf(projection))
|
|
53
|
+
&& networkEqual(projection.controller, trusted.controller) && projection.nodeId === trusted.nodeId
|
|
54
|
+
&& projection.runtimeNamespace === trusted.runtimeNamespace && projection.handoff);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/** Content binding only. The caller must resolve the exact current projection
|
|
58
|
+
* and authenticate/fence the current physical peer before and after native work. */
|
|
59
|
+
export const bindGetRuntimeManagedVpnCredentialRequestV1 = async (value: unknown, projectionValue: unknown,
|
|
60
|
+
trustedSessionValue: unknown): Promise<IGetRuntimeManagedVpnCredentialRequestV1> => {
|
|
61
|
+
try {
|
|
62
|
+
const request = snapshotGetRuntimeManagedVpnCredentialRequestV1(value);
|
|
63
|
+
const trusted = snapshotRuntimeSessionBindingV1(trustedSessionValue);
|
|
64
|
+
const projection = await validateRuntimeNetworkProjectionV1(projectionValue);
|
|
65
|
+
bindRequest(request, projection, trusted);
|
|
66
|
+
return request;
|
|
67
|
+
} catch { return failNetwork(); }
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/** Bind the secret response to the original request and exact selected router
|
|
71
|
+
* UDP endpoint. Time is caller-qualified; this helper does not sample a clock,
|
|
72
|
+
* authenticate a transport, admit policy or prove a running managed connection. */
|
|
73
|
+
export const bindGetRuntimeManagedVpnCredentialResponseV1 = async (value: unknown, requestValue: unknown,
|
|
74
|
+
projectionValue: unknown, trustedSessionValue: unknown, nowValue: unknown): Promise<IGetRuntimeManagedVpnCredentialResponseV1> => {
|
|
75
|
+
try {
|
|
76
|
+
const response = snapshotGetRuntimeManagedVpnCredentialResponseV1(value);
|
|
77
|
+
const request = snapshotGetRuntimeManagedVpnCredentialRequestV1(requestValue);
|
|
78
|
+
const trusted = snapshotRuntimeSessionBindingV1(trustedSessionValue), now = networkCounter(nowValue);
|
|
79
|
+
const projection = await validateRuntimeNetworkProjectionV1(projectionValue);
|
|
80
|
+
bindRequest(request, projection, trusted);
|
|
81
|
+
requireNetwork(networkEqual(response.session, request.session) && networkEqual(response.projection, request.projection));
|
|
82
|
+
requireNetwork(projection.router?.platformEndpointIds.includes(response.relay.id));
|
|
83
|
+
const endpoint = projection.protectedAuthority.platformEndpoints.find(item => item.id === response.relay.id);
|
|
84
|
+
requireNetwork(endpoint && endpoint.protocol === 'udp' && endpoint.address === response.relay.address && endpoint.port === response.relay.port);
|
|
85
|
+
requireNetwork(projection.dns.notBefore <= now && now < response.expiresAt && response.expiresAt <= projection.dns.expiresAt);
|
|
86
|
+
return response;
|
|
87
|
+
} catch { return failNetwork(); }
|
|
88
|
+
};
|
|
@@ -3,6 +3,16 @@ import type * as data from '../data/runtimesession.js';
|
|
|
3
3
|
import type * as terminal from '../data/runtimeterminalreceipt.js';
|
|
4
4
|
import type * as network from '../data/networkdelivery.js';
|
|
5
5
|
import type * as protection from '../data/networkprotection.js';
|
|
6
|
+
import type * as credential from '../data/networkcredential.js';
|
|
7
|
+
|
|
8
|
+
/** Current-peer, exact-projection authorization; response contains secret keys. */
|
|
9
|
+
export interface IReq_Pallet_Controller_GetRuntimeManagedVpnCredentialV1 extends plugins.typedrequestInterfaces.implementsTR<
|
|
10
|
+
plugins.typedrequestInterfaces.ITypedRequest, IReq_Pallet_Controller_GetRuntimeManagedVpnCredentialV1
|
|
11
|
+
> {
|
|
12
|
+
method: 'getRuntimeManagedVpnCredentialV1';
|
|
13
|
+
request: credential.IGetRuntimeManagedVpnCredentialRequestV1;
|
|
14
|
+
response: credential.IGetRuntimeManagedVpnCredentialResponseV1;
|
|
15
|
+
}
|
|
6
16
|
|
|
7
17
|
/** Current authenticated peer reports its durable complete native protection journal. */
|
|
8
18
|
export interface IReq_Pallet_Controller_ReportRuntimeNetworkProtectionV1 extends plugins.typedrequestInterfaces.implementsTR<
|