@serve.zone/interfaces 23.0.4 → 23.1.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/readme.md CHANGED
@@ -67,6 +67,46 @@ Primary v23 additions include:
67
67
  - Mandatory `IImmutableContainerInvocationV1` evidence on immutable image
68
68
  deployment plans.
69
69
 
70
+ ### Secrets v23.1 Runtime Registration And Reporting
71
+
72
+ The Node-only `@serve.zone/interfaces/runtime` export adds the live contract
73
+ that Cloudly must validate before publishing secret-bearing desired state to a
74
+ Coreflow connection:
75
+
76
+ - `getSecretRecipientEnrollmentState` returns either an exact generation-zero
77
+ empty state or the complete valid recipient set for the cluster derived from
78
+ the verified JWT.
79
+ - `ICoreflowSecretRuntimeRegistrationV1` binds a reporter session to the exact
80
+ authoritative schedulable target-node set, required secret capabilities,
81
+ active recipient, approved WorkloadInit OCI index, and exact per-platform
82
+ manifest and installed-executable digests.
83
+ - `validateCoreflowSecretRuntimeRegistration` compares the registration with a
84
+ trusted expectation built by Cloudly, including the live reporter session.
85
+ Missing, extra, duplicate, reordered, or mismatched node evidence fails
86
+ closed. Consumers must discard the registration on transport disconnect, tag
87
+ removal or replacement, or any live session, placement, artifact, or
88
+ recipient expectation change before publishing more secret-bearing state.
89
+ - `reportSecretDeploymentState` reports only `applying`, `applied`, `drifted`,
90
+ or `failed` for the manifest and plan revision selected by Cloudly. The
91
+ validator receives the trusted cluster ID after JWT verification and the
92
+ trusted live reporter session. Wire-provided manifest scope is checked
93
+ against, and never replaces, that trusted authority.
94
+
95
+ The package validates report shape, digest, trusted cluster, and trusted live
96
+ session; it does not persist replay state or mutate deployment plans. Deployment
97
+ report consumers must persist an atomic receipt keyed by the verified cluster,
98
+ reporter session, service, and positive sequence. The report digest uses
99
+ fixed-order JSON and excludes only the JWT identity and `reportDigest`. The
100
+ consumer accepts the exact next sequence once, returns the prior response for a
101
+ same-digest replay, rejects a different-digest replay, and ensures a plan
102
+ revision CAS failure consumes neither the sequence nor a receipt. Timestamps
103
+ are informational and never replace live session, placement, artifact,
104
+ recipient, sequence, or plan-revision fences.
105
+
106
+ `createWorkloadInitEnvironmentMap` now rejects manifests without any
107
+ `launcher-environment` delivery. Consumers must bypass WorkloadInit for
108
+ file-only manifests.
109
+
70
110
  ## Portable Storage Contracts
71
111
 
72
112
  App Store templates can declare logical, template-local `storageClasses` and
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '23.0.4',
6
+ version: '23.1.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  }
@@ -71,6 +71,8 @@ export interface ICoreflowRuntimeCapabilities {
71
71
  sealedSecretMaterialVersion: 1;
72
72
  secretRecipientEnrollmentVersion: 1;
73
73
  workloadInitEnvironmentVersion: 1;
74
+ /** Coreflow can submit replay-safe schema-v1 secret deployment reports. */
75
+ secretDeploymentReportVersion?: 1;
74
76
  }
75
77
 
76
78
  export type TImmutableContainerPlatform = 'linux/amd64' | 'linux/arm64';
package/ts/data/secret.ts CHANGED
@@ -922,7 +922,7 @@ export const validateResolvedSecretManifest = (
922
922
  return errors;
923
923
  };
924
924
 
925
- const validateResolvedSecretManifestReference = (
925
+ const validateResolvedSecretManifestReferenceAtPath = (
926
926
  referenceArg: unknown,
927
927
  expectedClusterIdArg: string,
928
928
  pathArg: string,
@@ -958,6 +958,25 @@ const validateResolvedSecretManifestReference = (
958
958
  return [];
959
959
  };
960
960
 
961
+ /** Strict public validator for a cluster-scoped resolved manifest reference. */
962
+ export const validateResolvedSecretManifestReference = (
963
+ referenceArg: unknown,
964
+ expectedClusterIdArg: string,
965
+ ): string[] => {
966
+ try {
967
+ if (!isSecretIdentifier(expectedClusterIdArg)) {
968
+ return ['expected cluster id must be canonical'];
969
+ }
970
+ return validateResolvedSecretManifestReferenceAtPath(
971
+ referenceArg,
972
+ expectedClusterIdArg,
973
+ 'resolved secret manifest reference',
974
+ );
975
+ } catch {
976
+ return ['resolved secret manifest reference must be safely inspectable'];
977
+ }
978
+ };
979
+
961
980
  export const validateServiceSecretDeploymentPlan = (
962
981
  planArg: unknown,
963
982
  expectedTargetClusterIdsArg?: string[],
@@ -992,7 +1011,7 @@ export const validateServiceSecretDeploymentPlan = (
992
1011
  expectedClusterIdArg: string,
993
1012
  pathArg: string,
994
1013
  ): void => {
995
- const referenceErrors = validateResolvedSecretManifestReference(
1014
+ const referenceErrors = validateResolvedSecretManifestReferenceAtPath(
996
1015
  referenceArg,
997
1016
  expectedClusterIdArg,
998
1017
  pathArg,
@@ -1183,6 +1202,9 @@ export const createWorkloadInitEnvironmentMap = async (
1183
1202
  source: createLauncherSecretSourcePath(resource),
1184
1203
  };
1185
1204
  }));
1205
+ if (entries.length === 0) {
1206
+ throw new Error('workload init map requires at least one launcher-environment delivery');
1207
+ }
1186
1208
  entries.sort((leftArg, rightArg) => (
1187
1209
  leftArg.variableName < rightArg.variableName
1188
1210
  ? -1