@serve.zone/interfaces 27.5.0 → 28.0.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,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026-09-05 - 28.0.0
4
+
5
+ ### Breaking Changes
6
+
7
+ - require identity for node config and add credential administration contracts (node-credentials)
8
+ - Add node credential metadata, mutation precondition, and mutation result interfaces for spark and pallet purposes.
9
+ - Add getNodeCredential, rotateNodeCredential, and revokeNodeCredential typed request contracts with infrastructure-admin identity requirements.
10
+ - Require identity on getNodeConfig requests, changing the existing request shape.
11
+ - Document node credential administration semantics and add type-level contract tests.
12
+
3
13
  ## 2026-09-05 - 27.5.0
4
14
 
5
15
  ### Features
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '27.5.0',
6
+ version: '28.0.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLHVGQUF1RjtDQUNyRyxDQUFBIn0=
@@ -20,6 +20,7 @@ export * from './immutableimage.js';
20
20
  export * from './isolatedrestore.js';
21
21
  export * from './isolatedrestore.golden.js';
22
22
  export * from './mail.js';
23
+ export * from './nodecredential.js';
23
24
  export * from './registry.js';
24
25
  export * from './runtimeassignment.js';
25
26
  export * from './secret.js';
@@ -20,6 +20,7 @@ export * from './immutableimage.js';
20
20
  export * from './isolatedrestore.js';
21
21
  export * from './isolatedrestore.golden.js';
22
22
  export * from './mail.js';
23
+ export * from './nodecredential.js';
23
24
  export * from './registry.js';
24
25
  export * from './runtimeassignment.js';
25
26
  export * from './secret.js';
@@ -36,4 +37,4 @@ export * from './traffic.js';
36
37
  export * from './user.js';
37
38
  export * from './version.js';
38
39
  export * from './webpush.js';
39
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxlQUFlLENBQUM7QUFDOUIsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMseUJBQXlCLENBQUM7QUFDeEMsY0FBYywwQkFBMEIsQ0FBQztBQUN6QyxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxVQUFVLENBQUM7QUFDekIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxZQUFZLENBQUM7QUFDM0IsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLGdCQUFnQixDQUFDO0FBQy9CLGNBQWMsWUFBWSxDQUFDO0FBQzNCLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsV0FBVyxDQUFDO0FBQzFCLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxvQkFBb0IsQ0FBQztBQUNuQyxjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLFdBQVcsQ0FBQztBQUMxQixjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLGNBQWMsQ0FBQyJ9
40
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxlQUFlLENBQUM7QUFDOUIsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMseUJBQXlCLENBQUM7QUFDeEMsY0FBYywwQkFBMEIsQ0FBQztBQUN6QyxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxVQUFVLENBQUM7QUFDekIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxZQUFZLENBQUM7QUFDM0IsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLGdCQUFnQixDQUFDO0FBQy9CLGNBQWMsWUFBWSxDQUFDO0FBQzNCLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsV0FBVyxDQUFDO0FBQzFCLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxlQUFlLENBQUM7QUFDOUIsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGdCQUFnQixDQUFDO0FBQy9CLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsY0FBYyxlQUFlLENBQUM7QUFDOUIsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxtQkFBbUIsQ0FBQztBQUNsQyxjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsV0FBVyxDQUFDO0FBQzFCLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsY0FBYyxDQUFDIn0=
@@ -0,0 +1,38 @@
1
+ /** Independent infrastructure credentials; neither purpose grants workload RBAC. */
2
+ export type TNodeCredentialPurpose = 'spark' | 'pallet';
3
+ /**
4
+ * Public inspection and mutation-result metadata. Never includes bearer material,
5
+ * hashes, socket peer IDs or controller process IDs. On replay this is historical
6
+ * evidence, not an assertion that a credential or reporter session is still live.
7
+ */
8
+ export interface INodeCredentialMetadataV1 {
9
+ schemaVersion: 1;
10
+ nodeId: string;
11
+ purpose: TNodeCredentialPurpose;
12
+ state: 'active' | 'revoked';
13
+ generation: number;
14
+ /** Migrated Spark credentials remain usable only until their staged rotation. */
15
+ requiresRotation: boolean;
16
+ sessionEpoch: number;
17
+ sessionId: string | null;
18
+ createdAt: number;
19
+ updatedAt: number;
20
+ }
21
+ /**
22
+ * Infrastructure-admin mutation preconditions. Both counters are exact CAS
23
+ * preconditions, not minimums. Retrying must retain this complete input and the
24
+ * original mutationId; a changed request with the same ID must fail closed.
25
+ */
26
+ export interface INodeCredentialMutationPreconditionsV1 {
27
+ schemaVersion: 1;
28
+ nodeId: string;
29
+ purpose: TNodeCredentialPurpose;
30
+ mutationId: string;
31
+ expectedGeneration: number;
32
+ expectedSessionEpoch: number;
33
+ }
34
+ export interface INodeCredentialMutationResultV1 {
35
+ metadata: INodeCredentialMetadataV1;
36
+ /** A replay returns the original result without restoring its authority. */
37
+ replayed: boolean;
38
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZWNyZWRlbnRpYWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL25vZGVjcmVkZW50aWFsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
@@ -4,15 +4,54 @@ import type { ICluster } from '../data/cluster.js';
4
4
  import type { IClusterNode, IClusterNodeMetrics, INodeAction, INodeMetricsSample, ISparkNodeRuntimeInfo, TNodeActionName } from '../data/clusternode.js';
5
5
  import type { IDeployment } from '../data/deployment.js';
6
6
  import type { IIdentity } from '../data/user.js';
7
- export interface IRequest_Any_Cloudly_GetNodeConfig {
7
+ import type { INodeCredentialMetadataV1, INodeCredentialMutationPreconditionsV1, INodeCredentialMutationResultV1, TNodeCredentialPurpose } from '../data/nodecredential.js';
8
+ /** Requires verified platform-infrastructure admin authority; returns public data only. */
9
+ export interface IRequest_Any_Cloudly_GetNodeConfig extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IRequest_Any_Cloudly_GetNodeConfig> {
8
10
  method: 'getNodeConfig';
9
11
  request: {
12
+ identity: IIdentity;
10
13
  nodeId: string;
11
14
  };
12
15
  response: {
13
16
  configData: IClusterNode;
14
17
  };
15
18
  }
19
+ /** These credential methods require verified infrastructure-admin authority. */
20
+ export interface IReq_Any_Cloudly_GetNodeCredential extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_GetNodeCredential> {
21
+ method: 'getNodeCredential';
22
+ request: {
23
+ identity: IIdentity;
24
+ nodeId: string;
25
+ purpose: TNodeCredentialPurpose;
26
+ };
27
+ response: {
28
+ metadata: INodeCredentialMetadataV1 | null;
29
+ };
30
+ }
31
+ export interface IReq_Any_Cloudly_RotateNodeCredential extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_RotateNodeCredential> {
32
+ method: 'rotateNodeCredential';
33
+ request: {
34
+ identity: IIdentity;
35
+ mutation: INodeCredentialMutationPreconditionsV1 & {
36
+ /**
37
+ * SHA-256(token UTF-8 bytes), exactly 64 lowercase hexadecimal characters.
38
+ * The node must durably retain its pending CSPRNG credential and mutation
39
+ * identity before this request. A metadata-only retry never issues plaintext.
40
+ * Treat this request field as sensitive; never include it in hooks or logs.
41
+ */
42
+ newTokenHash: string;
43
+ };
44
+ };
45
+ response: INodeCredentialMutationResultV1;
46
+ }
47
+ export interface IReq_Any_Cloudly_RevokeNodeCredential extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_RevokeNodeCredential> {
48
+ method: 'revokeNodeCredential';
49
+ request: {
50
+ identity: IIdentity;
51
+ mutation: INodeCredentialMutationPreconditionsV1;
52
+ };
53
+ response: INodeCredentialMutationResultV1;
54
+ }
16
55
  export interface IRequest_Any_Cloudly_GetNodesByCluster {
17
56
  method: 'getNodesByCluster';
18
57
  request: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serve.zone/interfaces",
3
- "version": "27.5.0",
3
+ "version": "28.0.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
@@ -47,6 +47,33 @@ validator; unlike `@serve.zone/interfaces/runtime`, it does not load the general
47
47
  runtime graph, `plugins.js`, SmartCrypto, TypedRequest, Corestore, or settlement
48
48
  runtime modules.
49
49
 
50
+ ### Node Credential Administration
51
+
52
+ `requests.node` defines `getNodeCredential`, `rotateNodeCredential` and
53
+ `revokeNodeCredential` for verified platform-infrastructure administrators.
54
+ `getNodeConfig` now also requires `identity`; callers using the previous
55
+ unauthenticated request shape must update. Its response remains the public
56
+ `IClusterNode`, never a persisted backend document.
57
+
58
+ `data.INodeCredentialMetadataV1` separates `spark` and `pallet` purposes and
59
+ exposes lifecycle state, generation, rotation-required status and session epoch,
60
+ but no bearer, hash, socket peer or controller process identity. Infrastructure
61
+ credentials do not grant organization or workload permissions.
62
+
63
+ Mutations require the exact generation and session epoch plus a stable mutation
64
+ ID. Rotation takes the SHA-256 hash of a node-generated CSPRNG credential that the
65
+ node has already durably retained with that mutation ID. Lost-response retries
66
+ repeat the complete request and receive the original metadata, never newly minted
67
+ plaintext. A replay result is historical and cannot authorize a current session.
68
+ Treat rotation request hashes as sensitive in transport hooks and logs.
69
+
70
+ These types do not implement authentication, storage, enrollment or endpoints.
71
+ Cloudly must verify current administrator authority, validate complete inputs,
72
+ atomically persist the credential transition and immutable actor-bound receipt,
73
+ and fence subsequent control effects against current durable credential/session
74
+ authority. Node identity storage and transport integration must be qualified
75
+ before enabling rotation or Pallet enrollment.
76
+
50
77
  ### Node-Bound Runtime Assignments
51
78
 
52
79
  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: '27.5.0',
6
+ version: '28.0.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  }
package/ts/data/index.ts CHANGED
@@ -20,6 +20,7 @@ export * from './immutableimage.js';
20
20
  export * from './isolatedrestore.js';
21
21
  export * from './isolatedrestore.golden.js';
22
22
  export * from './mail.js';
23
+ export * from './nodecredential.js';
23
24
  export * from './registry.js';
24
25
  export * from './runtimeassignment.js';
25
26
  export * from './secret.js';
@@ -0,0 +1,41 @@
1
+ /** Independent infrastructure credentials; neither purpose grants workload RBAC. */
2
+ export type TNodeCredentialPurpose = 'spark' | 'pallet';
3
+
4
+ /**
5
+ * Public inspection and mutation-result metadata. Never includes bearer material,
6
+ * hashes, socket peer IDs or controller process IDs. On replay this is historical
7
+ * evidence, not an assertion that a credential or reporter session is still live.
8
+ */
9
+ export interface INodeCredentialMetadataV1 {
10
+ schemaVersion: 1;
11
+ nodeId: string;
12
+ purpose: TNodeCredentialPurpose;
13
+ state: 'active' | 'revoked';
14
+ generation: number;
15
+ /** Migrated Spark credentials remain usable only until their staged rotation. */
16
+ requiresRotation: boolean;
17
+ sessionEpoch: number;
18
+ sessionId: string | null;
19
+ createdAt: number;
20
+ updatedAt: number;
21
+ }
22
+
23
+ /**
24
+ * Infrastructure-admin mutation preconditions. Both counters are exact CAS
25
+ * preconditions, not minimums. Retrying must retain this complete input and the
26
+ * original mutationId; a changed request with the same ID must fail closed.
27
+ */
28
+ export interface INodeCredentialMutationPreconditionsV1 {
29
+ schemaVersion: 1;
30
+ nodeId: string;
31
+ purpose: TNodeCredentialPurpose;
32
+ mutationId: string;
33
+ expectedGeneration: number;
34
+ expectedSessionEpoch: number;
35
+ }
36
+
37
+ export interface INodeCredentialMutationResultV1 {
38
+ metadata: INodeCredentialMetadataV1;
39
+ /** A replay returns the original result without restoring its authority. */
40
+ replayed: boolean;
41
+ }
@@ -4,10 +4,21 @@ import type { ICluster } from '../data/cluster.js';
4
4
  import type { IClusterNode, IClusterNodeMetrics, INodeAction, INodeMetricsSample, ISparkNodeRuntimeInfo, TNodeActionName } from '../data/clusternode.js';
5
5
  import type { IDeployment } from '../data/deployment.js';
6
6
  import type { IIdentity } from '../data/user.js';
7
+ import type {
8
+ INodeCredentialMetadataV1,
9
+ INodeCredentialMutationPreconditionsV1,
10
+ INodeCredentialMutationResultV1,
11
+ TNodeCredentialPurpose,
12
+ } from '../data/nodecredential.js';
7
13
 
8
- export interface IRequest_Any_Cloudly_GetNodeConfig {
14
+ /** Requires verified platform-infrastructure admin authority; returns public data only. */
15
+ export interface IRequest_Any_Cloudly_GetNodeConfig extends plugins.typedrequestInterfaces.implementsTR<
16
+ plugins.typedrequestInterfaces.ITypedRequest,
17
+ IRequest_Any_Cloudly_GetNodeConfig
18
+ > {
9
19
  method: 'getNodeConfig';
10
20
  request: {
21
+ identity: IIdentity;
11
22
  nodeId: string;
12
23
  };
13
24
  response: {
@@ -15,6 +26,54 @@ export interface IRequest_Any_Cloudly_GetNodeConfig {
15
26
  };
16
27
  }
17
28
 
29
+ /** These credential methods require verified infrastructure-admin authority. */
30
+ export interface IReq_Any_Cloudly_GetNodeCredential extends plugins.typedrequestInterfaces.implementsTR<
31
+ plugins.typedrequestInterfaces.ITypedRequest,
32
+ IReq_Any_Cloudly_GetNodeCredential
33
+ > {
34
+ method: 'getNodeCredential';
35
+ request: {
36
+ identity: IIdentity;
37
+ nodeId: string;
38
+ purpose: TNodeCredentialPurpose;
39
+ };
40
+ response: {
41
+ metadata: INodeCredentialMetadataV1 | null;
42
+ };
43
+ }
44
+
45
+ export interface IReq_Any_Cloudly_RotateNodeCredential extends plugins.typedrequestInterfaces.implementsTR<
46
+ plugins.typedrequestInterfaces.ITypedRequest,
47
+ IReq_Any_Cloudly_RotateNodeCredential
48
+ > {
49
+ method: 'rotateNodeCredential';
50
+ request: {
51
+ identity: IIdentity;
52
+ mutation: INodeCredentialMutationPreconditionsV1 & {
53
+ /**
54
+ * SHA-256(token UTF-8 bytes), exactly 64 lowercase hexadecimal characters.
55
+ * The node must durably retain its pending CSPRNG credential and mutation
56
+ * identity before this request. A metadata-only retry never issues plaintext.
57
+ * Treat this request field as sensitive; never include it in hooks or logs.
58
+ */
59
+ newTokenHash: string;
60
+ };
61
+ };
62
+ response: INodeCredentialMutationResultV1;
63
+ }
64
+
65
+ export interface IReq_Any_Cloudly_RevokeNodeCredential extends plugins.typedrequestInterfaces.implementsTR<
66
+ plugins.typedrequestInterfaces.ITypedRequest,
67
+ IReq_Any_Cloudly_RevokeNodeCredential
68
+ > {
69
+ method: 'revokeNodeCredential';
70
+ request: {
71
+ identity: IIdentity;
72
+ mutation: INodeCredentialMutationPreconditionsV1;
73
+ };
74
+ response: INodeCredentialMutationResultV1;
75
+ }
76
+
18
77
  export interface IRequest_Any_Cloudly_GetNodesByCluster {
19
78
  method: 'getNodesByCluster';
20
79
  request: {