@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 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.11.0',
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=
@@ -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';
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxlQUFlLENBQUM7QUFDOUIsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMseUJBQXlCLENBQUM7QUFDeEMsY0FBYywwQkFBMEIsQ0FBQztBQUN6QyxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxVQUFVLENBQUM7QUFDekIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxZQUFZLENBQUM7QUFDM0IsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLGdCQUFnQixDQUFDO0FBQy9CLGNBQWMsWUFBWSxDQUFDO0FBQzNCLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsV0FBVyxDQUFDO0FBQzFCLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsc0JBQXNCLENBQUM7QUFDckMsY0FBYyx3QkFBd0IsQ0FBQztBQUV2QyxjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLGVBQWUsQ0FBQztBQUM5QixjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLGVBQWUsQ0FBQztBQUM5QixjQUFjLHNCQUFzQixDQUFDO0FBQ3JDLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxtQkFBbUIsQ0FBQztBQUNsQyxjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsV0FBVyxDQUFDO0FBQzFCLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsY0FBYyxDQUFDIn0=
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serve.zone/interfaces",
3
- "version": "30.11.0",
3
+ "version": "30.12.0",
4
4
  "private": false,
5
5
  "description": "Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.",
6
6
  "exports": {
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,
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '30.11.0',
6
+ version: '30.12.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  }
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<