import * as plugins from './plugins.js'; import type { IActiveSecretRecipientMetadata, IClusterRuntimeTargetSetReadyV1, IClusterRuntimeTargetV1, IClusterSecretDeploymentState, ICoreflowRuntimeCapabilities, IIdentityCredential, IResolvedSecretManifest, IResolvedSecretManifestReference, TSha256Digest, TImmutableContainerPlatform, TSecretRecipientMetadata, } from './data/index.js'; import { createResolvedSecretMaterialEnvelopeContext, createSecretRecipientEnrollmentChallengeContext, resolvedSecretManifestReferencesEqual, validateResolvedSecretManifest, validateResolvedSecretManifestReference, validateSecretRecipientMetadata, validateSecretRecipientSet, verifySecretEnvelopeContext, verifyResolvedSecretManifestDigest, } from './data/secret.js'; import { isClusterRuntimeTargetSetFresh, validateClusterRuntimeTargetSet, } from './data/clusternode.js'; import { isSha256Digest } from './data/immutableimage.js'; import type { IWorkloadInitActiveApprovalAuthorityV1, IWorkloadInitApprovalAuthorityReferenceV1, IWorkloadInitApprovedArtifactV1, } from './runtime.workloadinit.js'; import { validateWorkloadInitActiveApprovalAuthority, validateWorkloadInitApprovalAuthorityReference, } from './runtime.workloadinit.js'; export * from './runtime.workloadinit.js'; export * from './runtime.corestore.js'; export * from './runtime.cloudlylegacydeploymentsettlement.js'; export interface ISealedResolvedSecretMaterialEntry { secretVersionId: string; envelope: plugins.smartcrypto.IX25519EnvelopeV1; } /** Runtime-only material. No plaintext value is represented in this DTO. */ export interface ISealedResolvedSecretMaterial { schemaVersion: 1; /** Full schema-v2 value-free manifest used for digest and rollout verification. */ manifest: IResolvedSecretManifest; /** Sorted exact coverage of the manifest's pinned versions. */ entries: ISealedResolvedSecretMaterialEntry[]; } export interface ISecretMaterialRequestFence { serviceId: string; imageRolloutId: string; imageRolloutGeneration: number; requestedImageDigest: TSha256Digest; secretRolloutId: string; secretRolloutGeneration: number; manifestId: string; manifestDigest: TSha256Digest; expectedRecipientKeyId: string; } /** Request fence plus trusted local scope derived from the verified cluster identity. */ export interface ISecretMaterialExpectation extends ISecretMaterialRequestFence { organizationId: string; clusterId: string; } /** * Parses every envelope with SmartCrypto, verifies its bound context digest, * and checks sorted exact version coverage. It never receives a private key * and never decrypts material. */ export const verifySealedResolvedSecretMaterial = async ( materialArg: unknown, expectedArg: ISecretMaterialExpectation, ): Promise => { if (!materialArg || typeof materialArg !== 'object' || Array.isArray(materialArg)) return false; const material = materialArg as Partial; if (JSON.stringify(Object.keys(material).sort()) !== JSON.stringify([ 'entries', 'manifest', 'schemaVersion', ])) { return false; } if (material.schemaVersion !== 1 || !material.manifest || !Array.isArray(material.entries)) { return false; } if (validateResolvedSecretManifest(material.manifest).length > 0 || !await verifyResolvedSecretManifestDigest(material.manifest)) { return false; } if (material.manifest.organizationId !== expectedArg.organizationId || material.manifest.clusterId !== expectedArg.clusterId || material.manifest.serviceId !== expectedArg.serviceId || material.manifest.imageRolloutId !== expectedArg.imageRolloutId || material.manifest.imageRolloutGeneration !== expectedArg.imageRolloutGeneration || material.manifest.requestedImageDigest !== expectedArg.requestedImageDigest || material.manifest.secretRolloutId !== expectedArg.secretRolloutId || material.manifest.secretRolloutGeneration !== expectedArg.secretRolloutGeneration || material.manifest.id !== expectedArg.manifestId || material.manifest.digest !== expectedArg.manifestDigest) { return false; } if (material.entries.length > 256 || material.entries.length !== material.manifest.entries.length) { return false; } const expectedVersionIds = material.manifest.entries .map((entryArg) => entryArg.secretVersionId) .sort(); const actualVersionIds = material.entries.map((entryArg) => entryArg.secretVersionId); if (new Set(actualVersionIds).size !== actualVersionIds.length || JSON.stringify(actualVersionIds) !== JSON.stringify(expectedVersionIds)) { return false; } const manifestEntriesByVersion = new Map(material.manifest.entries.map((entryArg) => [ entryArg.secretVersionId, entryArg, ])); for (const entry of material.entries) { if (!entry || typeof entry !== 'object' || typeof entry.secretVersionId !== 'string') return false; if (JSON.stringify(Object.keys(entry).sort()) !== JSON.stringify([ 'envelope', 'secretVersionId', ])) { return false; } const manifestEntry = manifestEntriesByVersion.get(entry.secretVersionId); if (!manifestEntry) return false; let envelope: plugins.smartcrypto.IX25519EnvelopeV1; try { envelope = plugins.smartcrypto.parseX25519Envelope(entry.envelope); } catch { return false; } if (envelope.recipientKeyId !== expectedArg.expectedRecipientKeyId) return false; const context = createResolvedSecretMaterialEnvelopeContext({ recipientKeyId: expectedArg.expectedRecipientKeyId, organizationId: material.manifest.organizationId, clusterId: material.manifest.clusterId, serviceId: material.manifest.serviceId, imageRolloutId: material.manifest.imageRolloutId, imageRolloutGeneration: material.manifest.imageRolloutGeneration, requestedImageDigest: material.manifest.requestedImageDigest, secretRolloutId: material.manifest.secretRolloutId, secretRolloutGeneration: material.manifest.secretRolloutGeneration, manifestId: material.manifest.id, manifestDigest: material.manifest.digest, secretId: manifestEntry.secretId, secretVersionId: manifestEntry.secretVersionId, }); if (!await verifySecretEnvelopeContext(envelope, context)) return false; } return true; }; /** Organization and cluster are derived exclusively from the verified cluster JWT. */ export interface IReq_GetResolvedSecretMaterial extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_GetResolvedSecretMaterial > { method: 'getResolvedSecretMaterial'; request: ISecretMaterialRequestFence & { identity: IIdentityCredential; }; response: { material: ISealedResolvedSecretMaterial; }; } export interface ISecretRecipientEnrollmentChallengeV1 { schemaVersion: 1; enrollmentId: string; clusterId: string; recipientKeyId: string; publicKey: string; generation: number; expiresAt: number; /** Sealed random 32-byte challenge; plaintext is never persisted or returned. */ envelope: plugins.smartcrypto.IX25519EnvelopeV1; } /** * Cluster scope is derived from the JWT. The server persists only a one-time * challenge hash plus expiry and consumes it with generation CAS; reuse, * expiry, mismatch, and replay are rejected. Private keys and challenge * plaintext have no persistence DTO. */ export interface IReq_BeginSecretRecipientEnrollment extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_BeginSecretRecipientEnrollment > { method: 'beginSecretRecipientEnrollment'; request: { identity: IIdentityCredential; proposedRecipientKeyId: string; proposedPublicKey: string; expectedGeneration: number; }; response: { challenge: ISecretRecipientEnrollmentChallengeV1; }; } export interface IReq_CompleteSecretRecipientEnrollment extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_CompleteSecretRecipientEnrollment > { method: 'completeSecretRecipientEnrollment'; request: { identity: IIdentityCredential; enrollmentId: string; expectedGeneration: number; /** Canonical unpadded base64url response containing exactly 32 bytes. */ response: string; }; response: { recipient: TSecretRecipientMetadata; }; } const canonicalIdentifierRegex = /^[A-Za-z0-9][A-Za-z0-9:._-]{0,199}$/; const raw32ByteBase64UrlRegex = /^[A-Za-z0-9_-]{42}[AEIMQUYcgkosw048]$/; export const validateBeginSecretRecipientEnrollmentRequest = ( requestArg: unknown, ): string[] => { if (!requestArg || typeof requestArg !== 'object' || Array.isArray(requestArg)) { return ['enrollment request must be an object']; } const request = requestArg as Record; const errors: string[] = []; if (JSON.stringify(Object.keys(request).sort()) !== JSON.stringify([ 'expectedGeneration', 'identity', 'proposedPublicKey', 'proposedRecipientKeyId', ])) { errors.push('enrollment request must use its exact schema'); } if (!request.identity || typeof request.identity !== 'object' || typeof (request.identity as Record).jwt !== 'string') { errors.push('enrollment identity must be a JWT credential'); } if (typeof request.proposedRecipientKeyId !== 'string' || !canonicalIdentifierRegex.test(request.proposedRecipientKeyId)) { errors.push('proposed recipient key id must be canonical'); } if (typeof request.proposedPublicKey !== 'string' || !raw32ByteBase64UrlRegex.test(request.proposedPublicKey)) { errors.push('proposed public key must be canonical base64url raw X25519 material'); } if (!Number.isSafeInteger(request.expectedGeneration) || (request.expectedGeneration as number) < 0) { errors.push('expected generation must be a non-negative integer'); } if ('clusterId' in request || 'organizationId' in request) { errors.push('enrollment request must not select cluster or organization scope'); } return errors; }; export const validateSecretRecipientEnrollmentChallenge = async ( challengeArg: unknown, ): Promise => { if (!challengeArg || typeof challengeArg !== 'object' || Array.isArray(challengeArg)) { return ['enrollment challenge must be an object']; } const challenge = challengeArg as Record; const errors: string[] = []; if (JSON.stringify(Object.keys(challenge).sort()) !== JSON.stringify([ 'clusterId', 'enrollmentId', 'envelope', 'expiresAt', 'generation', 'publicKey', 'recipientKeyId', 'schemaVersion', ])) { errors.push('enrollment challenge must use its exact schema'); } for (const field of ['enrollmentId', 'clusterId', 'recipientKeyId'] as const) { if (typeof challenge[field] !== 'string' || !canonicalIdentifierRegex.test(challenge[field] as string)) { errors.push(`enrollment challenge ${field} must be canonical`); } } if (challenge.schemaVersion !== 1) errors.push('enrollment challenge schemaVersion must be 1'); if (typeof challenge.publicKey !== 'string' || !raw32ByteBase64UrlRegex.test(challenge.publicKey)) { errors.push('enrollment challenge public key must be canonical'); } if (!Number.isSafeInteger(challenge.generation) || (challenge.generation as number) < 1) { errors.push('enrollment challenge generation must be positive'); } if (!Number.isSafeInteger(challenge.expiresAt) || (challenge.expiresAt as number) < 1) { errors.push('enrollment challenge expiry must be positive'); } let envelope: plugins.smartcrypto.IX25519EnvelopeV1 | undefined; try { envelope = plugins.smartcrypto.parseX25519Envelope(challenge.envelope); } catch { errors.push('enrollment challenge envelope must be strict'); } if (envelope) { if (envelope.recipientKeyId !== challenge.recipientKeyId) { errors.push('enrollment challenge recipient does not match'); } if (!raw32ByteBase64UrlRegex.test(envelope.ciphertext)) { errors.push('enrollment challenge ciphertext must contain exactly 32 bytes'); } if (errors.length === 0) { const context = createSecretRecipientEnrollmentChallengeContext({ enrollmentId: challenge.enrollmentId as string, clusterId: challenge.clusterId as string, recipientKeyId: challenge.recipientKeyId as string, publicKey: challenge.publicKey as string, generation: challenge.generation as number, expiresAt: challenge.expiresAt as number, }); if (!await verifySecretEnvelopeContext(envelope, context)) { errors.push('enrollment challenge context does not match'); } } } return errors; }; export const validateCompleteSecretRecipientEnrollmentRequest = ( requestArg: unknown, ): string[] => { if (!requestArg || typeof requestArg !== 'object' || Array.isArray(requestArg)) { return ['enrollment completion must be an object']; } const request = requestArg as Record; const errors: string[] = []; if (JSON.stringify(Object.keys(request).sort()) !== JSON.stringify([ 'enrollmentId', 'expectedGeneration', 'identity', 'response', ])) { errors.push('enrollment completion must use its exact schema'); } if (!request.identity || typeof request.identity !== 'object' || typeof (request.identity as Record).jwt !== 'string') { errors.push('enrollment identity must be a JWT credential'); } if (typeof request.enrollmentId !== 'string' || !canonicalIdentifierRegex.test(request.enrollmentId)) { errors.push('enrollment id must be canonical'); } if (!Number.isSafeInteger(request.expectedGeneration) || (request.expectedGeneration as number) < 0) { errors.push('expected generation must be a non-negative integer'); } if (typeof request.response !== 'string' || !raw32ByteBase64UrlRegex.test(request.response)) { errors.push('enrollment response must be canonical base64url containing exactly 32 bytes'); } if ('clusterId' in request || 'organizationId' in request) { errors.push('enrollment completion must not select cluster or organization scope'); } return errors; }; export { validateSecretRecipientMetadata }; const runtimeIdentifierRegex = /^[A-Za-z0-9][A-Za-z0-9:._-]{0,199}$/; const runtimeFailureCodeRegex = /^[A-Z][A-Z0-9_]{0,127}$/; const runtimePlatforms = new Set([ 'linux/amd64', 'linux/arm64', ]); const maximumRuntimeNodes = 1024; const isRuntimeRecord = (valueArg: unknown): valueArg is Record => ( Boolean(valueArg) && typeof valueArg === 'object' && !Array.isArray(valueArg) ); const hasExactRuntimeKeys = ( valueArg: Record, keysArg: string[], ): boolean => JSON.stringify(Object.keys(valueArg).sort()) === JSON.stringify([...keysArg].sort()); const hasOnlyRuntimeKeys = ( valueArg: Record, keysArg: string[], ): boolean => Object.keys(valueArg).every((keyArg) => keysArg.includes(keyArg)); const isRuntimeIdentifier = (valueArg: unknown): valueArg is string => ( typeof valueArg === 'string' && runtimeIdentifierRegex.test(valueArg) ); const isPositiveSafeInteger = (valueArg: unknown): valueArg is number => ( Number.isSafeInteger(valueArg) && (valueArg as number) > 0 ); const computeRuntimeSha256 = async (inputArg: string): Promise => { const input = new TextEncoder().encode(inputArg); const digest = new Uint8Array(await globalThis.crypto.subtle.digest( 'SHA-256', input.buffer as ArrayBuffer, )); return `sha256:${[...digest] .map((byteArg) => byteArg.toString(16).padStart(2, '0')) .join('')}` as TSha256Digest; }; const computeRuntimeSha256Bytes = async ( inputArg: Uint8Array, ): Promise => { const digest = new Uint8Array(await globalThis.crypto.subtle.digest( 'SHA-256', new Uint8Array(inputArg), )); return `sha256:${[...digest] .map((byteArg) => byteArg.toString(16).padStart(2, '0')) .join('')}` as TSha256Digest; }; /** * Reproducible binding persisted inside a trusted Cloudly mutation receipt. * This value alone does not prove that Cloudly admitted the envelope. */ export interface ISecretEnvelopeAdmissionBindingV1 { schemaVersion: 1; recipientKeyId: string; recipientGeneration: number; envelopeDigest: TSha256Digest; requestContextDigest: TSha256Digest; } export const createSecretEnvelopeDigestInput = ( envelopeArg: unknown, ): string => { const envelope = plugins.smartcrypto.parseX25519Envelope(envelopeArg); return JSON.stringify({ schemaVersion: envelope.schemaVersion, profile: envelope.profile, recipientKeyId: envelope.recipientKeyId, ephemeralPublicKey: envelope.ephemeralPublicKey, nonce: envelope.nonce, ciphertext: envelope.ciphertext, tag: envelope.tag, contextDigest: envelope.contextDigest, }); }; export const computeSecretEnvelopeDigest = async ( envelopeArg: unknown, ): Promise => computeRuntimeSha256(createSecretEnvelopeDigestInput(envelopeArg)); export const computeSecretRequestContextDigest = async ( contextArg: Uint8Array, ): Promise => { if (!(contextArg instanceof Uint8Array)) { throw new Error('secret request context must be bytes'); } return computeRuntimeSha256Bytes(contextArg); }; export const validateSecretEnvelopeAdmissionBinding = ( bindingArg: unknown, ): string[] => { if (!isRuntimeRecord(bindingArg) || !hasExactRuntimeKeys(bindingArg, [ 'schemaVersion', 'recipientKeyId', 'recipientGeneration', 'envelopeDigest', 'requestContextDigest', ])) { return ['secret envelope admission binding must use its exact schema']; } const errors: string[] = []; if (bindingArg.schemaVersion !== 1) { errors.push('secret envelope admission binding schemaVersion must be 1'); } if (!isRuntimeIdentifier(bindingArg.recipientKeyId) || !isPositiveSafeInteger(bindingArg.recipientGeneration)) { errors.push('secret envelope admission binding recipient must be canonical'); } if (typeof bindingArg.envelopeDigest !== 'string' || !isSha256Digest(bindingArg.envelopeDigest) || typeof bindingArg.requestContextDigest !== 'string' || !isSha256Digest(bindingArg.requestContextDigest)) { errors.push('secret envelope admission binding digests must be canonical'); } return errors; }; export const createSecretEnvelopeAdmissionBinding = async ( recipientArg: IActiveSecretRecipientMetadata, envelopeArg: unknown, requestContextArg: Uint8Array, ): Promise => { if (validateSecretRecipientMetadata(recipientArg).length > 0 || recipientArg.lifecycleState !== 'active') { throw new Error('secret envelope admission requires the active recipient'); } const envelope = plugins.smartcrypto.parseX25519Envelope(envelopeArg); if (envelope.recipientKeyId !== recipientArg.recipientKeyId || !await verifySecretEnvelopeContext(envelope, requestContextArg)) { throw new Error('secret envelope admission binding does not match recipient and context'); } return { schemaVersion: 1, recipientKeyId: recipientArg.recipientKeyId, recipientGeneration: recipientArg.generation, envelopeDigest: await computeSecretEnvelopeDigest(envelope), requestContextDigest: await computeSecretRequestContextDigest(requestContextArg), }; }; export const verifySecretEnvelopeAdmissionBinding = async ( bindingArg: unknown, envelopeArg: unknown, requestContextArg: Uint8Array, ): Promise => { try { if (validateSecretEnvelopeAdmissionBinding(bindingArg).length > 0) return false; const binding = bindingArg as ISecretEnvelopeAdmissionBindingV1; const envelope = plugins.smartcrypto.parseX25519Envelope(envelopeArg); return envelope.recipientKeyId === binding.recipientKeyId && await verifySecretEnvelopeContext(envelope, requestContextArg) && binding.envelopeDigest === await computeSecretEnvelopeDigest(envelope) && binding.requestContextDigest === await computeSecretRequestContextDigest(requestContextArg); } catch { return false; } }; export type TSecretRecipientEnrollmentStateV1 = | { schemaVersion: 1; generation: 0; recipients: []; } | { schemaVersion: 1; generation: number; recipients: TSecretRecipientMetadata[]; }; /** Cluster scope is derived exclusively from the verified cluster JWT. */ export interface IReq_GetSecretRecipientEnrollmentState extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_GetSecretRecipientEnrollmentState > { method: 'getSecretRecipientEnrollmentState'; request: { identity: IIdentityCredential; }; response: TSecretRecipientEnrollmentStateV1; } export const validateGetSecretRecipientEnrollmentStateRequest = ( requestArg: unknown, ): string[] => { try { if (!isRuntimeRecord(requestArg) || !hasExactRuntimeKeys(requestArg, ['identity']) || !isRuntimeRecord(requestArg.identity) || !hasExactRuntimeKeys(requestArg.identity, ['jwt']) || typeof requestArg.identity.jwt !== 'string' || requestArg.identity.jwt.length === 0) { return ['secret recipient enrollment state request must contain only a JWT identity']; } return []; } catch { return ['secret recipient enrollment state request must be safely inspectable']; } }; export const validateSecretRecipientEnrollmentState = ( stateArg: unknown, ): string[] => { try { if (!isRuntimeRecord(stateArg) || !hasExactRuntimeKeys(stateArg, ['schemaVersion', 'generation', 'recipients'])) { return ['secret recipient enrollment state must use its exact schema']; } const errors: string[] = []; if (stateArg.schemaVersion !== 1) { errors.push('secret recipient enrollment state schemaVersion must be 1'); } if (stateArg.generation === 0) { if (!Array.isArray(stateArg.recipients) || stateArg.recipients.length !== 0) { errors.push('generation-zero enrollment state must have no recipients'); } return errors; } if (!isPositiveSafeInteger(stateArg.generation)) { errors.push('secret recipient enrollment state generation must be zero or positive'); } const recipientErrors = validateSecretRecipientSet(stateArg.recipients); errors.push(...recipientErrors.map((errorArg) => `enrollment state ${errorArg}`)); if (recipientErrors.length === 0) { const recipients = stateArg.recipients as TSecretRecipientMetadata[]; const greatestGeneration = Math.max(...recipients.map((recipientArg) => recipientArg.generation)); if (stateArg.generation !== greatestGeneration) { errors.push('secret recipient enrollment state generation must match the active generation'); } } return errors; } catch { return ['secret recipient enrollment state must be safely inspectable']; } }; export interface ICoreflowSecretRuntimeNodeTargetV2 extends IClusterRuntimeTargetV1 {} export interface ICoreflowSecretRuntimeNodeEvidenceV2 extends ICoreflowSecretRuntimeNodeTargetV2 { workloadInitPlatformManifestDigest: TSha256Digest; workloadInitExecutableDigest: TSha256Digest; } export interface ICoreflowSecretRuntimeRegistrationExpectationV2 { expectationVersion: 2; expectationDigest: TSha256Digest; reporterSessionId: string; targetAuthority: IClusterRuntimeTargetSetReadyV1; workloadInitAuthority: IWorkloadInitActiveApprovalAuthorityV1; activeRecipient: IActiveSecretRecipientMetadata; } /** Dedicated TypedSocket tag carrying ICoreflowSecretRuntimeRegistrationV2. */ export const coreflowSecretRuntimeRegistrationTagId = 'coreflowSecretRuntimeRegistration' as const; export type TCoreflowSecretRuntimeRegistrationExpectationResponseV2 = | { status: 'available'; expectation: ICoreflowSecretRuntimeRegistrationExpectationV2; } | { status: 'unavailable'; reason: | 'recipient-unavailable' | 'workloadinit-unconfigured' | 'workloadinit-revoked' | 'targets-unavailable'; }; /** Cluster scope is derived exclusively from the verified cluster JWT. */ export interface IReq_GetCoreflowSecretRuntimeRegistrationExpectation extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_GetCoreflowSecretRuntimeRegistrationExpectation > { method: 'getCoreflowSecretRuntimeRegistrationExpectation'; request: { identity: IIdentityCredential; }; response: TCoreflowSecretRuntimeRegistrationExpectationResponseV2; } export const validateGetCoreflowSecretRuntimeRegistrationExpectationRequest = ( requestArg: unknown, ): string[] => { try { if (!isRuntimeRecord(requestArg) || !hasExactRuntimeKeys(requestArg, ['identity']) || !isRuntimeRecord(requestArg.identity) || !hasExactRuntimeKeys(requestArg.identity, ['jwt']) || typeof requestArg.identity.jwt !== 'string' || requestArg.identity.jwt.length === 0) { return ['secret runtime registration expectation request must contain only a JWT identity']; } return []; } catch { return ['secret runtime registration expectation request must be safely inspectable']; } }; export interface ICoreflowSecretRuntimeRegistrationV2 { registrationVersion: 2; expectationDigest: TSha256Digest; reporterSessionId: string; registeredAt: number; targetGeneration: number; targetSetDigest: TSha256Digest; targets: ICoreflowSecretRuntimeNodeTargetV2[]; nodeEvidence: ICoreflowSecretRuntimeNodeEvidenceV2[]; capabilities: ICoreflowRuntimeCapabilities; activeRecipient: IActiveSecretRecipientMetadata; workloadInitAuthority: IWorkloadInitApprovalAuthorityReferenceV1; workloadInitImageIndexDigest: TSha256Digest; } const compareRuntimeTargets = ( leftArg: ICoreflowSecretRuntimeNodeTargetV2, rightArg: ICoreflowSecretRuntimeNodeTargetV2, ): number => { for (const [left, right] of [ [leftArg.cloudlyNodeId, rightArg.cloudlyNodeId], [leftArg.swarmClusterId, rightArg.swarmClusterId], [leftArg.swarmNodeId, rightArg.swarmNodeId], [leftArg.nodeName, rightArg.nodeName], [leftArg.platform, rightArg.platform], ]) { if (left < right) return -1; if (left > right) return 1; } return 0; }; const canonicalRuntimeTarget = ( targetArg: ICoreflowSecretRuntimeNodeTargetV2, ): ICoreflowSecretRuntimeNodeTargetV2 => ({ cloudlyNodeId: targetArg.cloudlyNodeId, swarmClusterId: targetArg.swarmClusterId, swarmNodeId: targetArg.swarmNodeId, nodeName: targetArg.nodeName, platform: targetArg.platform, }); const canonicalActiveRecipient = ( recipientArg: IActiveSecretRecipientMetadata, ): IActiveSecretRecipientMetadata => ({ schemaVersion: recipientArg.schemaVersion, recipientKeyId: recipientArg.recipientKeyId, publicKey: recipientArg.publicKey, generation: recipientArg.generation, activatedAt: recipientArg.activatedAt, lifecycleState: recipientArg.lifecycleState, }); export const createCoreflowSecretRuntimeRegistrationExpectationDigestInput = ( expectationArg: ICoreflowSecretRuntimeRegistrationExpectationV2, ): string => JSON.stringify({ schemaVersion: 2, purpose: 'serve.zone/coreflow-secret-runtime-expectation', reporterSessionId: expectationArg.reporterSessionId, targetAuthority: { cloudlyClusterId: expectationArg.targetAuthority.cloudlyClusterId, swarmClusterId: expectationArg.targetAuthority.swarmClusterId, generation: expectationArg.targetAuthority.generation, targetSetDigest: expectationArg.targetAuthority.targetSetDigest, }, workloadInitAuthority: { authorityVersion: expectationArg.workloadInitAuthority.authorityVersion, authorityGeneration: expectationArg.workloadInitAuthority.authorityGeneration, approvalDigest: expectationArg.workloadInitAuthority.approvalDigest, }, activeRecipient: canonicalActiveRecipient(expectationArg.activeRecipient), }); export const computeCoreflowSecretRuntimeRegistrationExpectationDigest = async ( expectationArg: ICoreflowSecretRuntimeRegistrationExpectationV2, ): Promise => computeRuntimeSha256( createCoreflowSecretRuntimeRegistrationExpectationDigestInput(expectationArg), ); const validateRuntimeTargets = ( targetsArg: unknown, pathArg: string, ): string[] => { if (!Array.isArray(targetsArg) || targetsArg.length === 0 || targetsArg.length > maximumRuntimeNodes) { return [`${pathArg} must be a non-empty bounded array`]; } const errors: string[] = []; let previous: ICoreflowSecretRuntimeNodeTargetV2 | undefined; const cloudlyNodeIds = new Set(); const swarmNodeScopes = new Set(); const nodeNames = new Set(); for (const [index, targetArg] of targetsArg.entries()) { if (!isRuntimeRecord(targetArg) || !hasExactRuntimeKeys(targetArg, [ 'cloudlyNodeId', 'swarmClusterId', 'swarmNodeId', 'nodeName', 'platform', ])) { errors.push(`${pathArg}[${index}] must use its exact schema`); continue; } if (!isRuntimeIdentifier(targetArg.cloudlyNodeId) || !isRuntimeIdentifier(targetArg.swarmClusterId) || !isRuntimeIdentifier(targetArg.swarmNodeId) || !isRuntimeIdentifier(targetArg.nodeName)) { errors.push(`${pathArg}[${index}] node identity must be canonical`); } if (!runtimePlatforms.has(targetArg.platform as TImmutableContainerPlatform)) { errors.push(`${pathArg}[${index}].platform must be supported`); } if (isRuntimeIdentifier(targetArg.cloudlyNodeId) && isRuntimeIdentifier(targetArg.swarmClusterId) && isRuntimeIdentifier(targetArg.swarmNodeId) && isRuntimeIdentifier(targetArg.nodeName) && runtimePlatforms.has(targetArg.platform as TImmutableContainerPlatform)) { const target = targetArg as unknown as ICoreflowSecretRuntimeNodeTargetV2; if (previous && compareRuntimeTargets(previous, target) >= 0) { errors.push(`${pathArg} must be uniquely sorted by runtime identity`); } previous = target; const swarmNodeScope = `${target.swarmClusterId}\0${target.swarmNodeId}`; if (cloudlyNodeIds.has(target.cloudlyNodeId)) { errors.push(`${pathArg} cloudlyNodeIds must be unique`); } if (swarmNodeScopes.has(swarmNodeScope)) { errors.push(`${pathArg} scoped swarmNodeIds must be unique`); } if (nodeNames.has(target.nodeName)) errors.push(`${pathArg} nodeNames must be unique`); cloudlyNodeIds.add(target.cloudlyNodeId); swarmNodeScopes.add(swarmNodeScope); nodeNames.add(target.nodeName); } } return errors; }; const activeRecipientFingerprint = (recipientArg: IActiveSecretRecipientMetadata): string => ( JSON.stringify(canonicalActiveRecipient(recipientArg)) ); /** * Validates only a Cloudly-created expectation. It does not establish the * private DSSE trust decision or Spark manager consensus that produced it. */ export const validateCoreflowSecretRuntimeRegistrationExpectation = async ( expectationArg: unknown, trustedNowArg: number, ): Promise => { try { const errors: string[] = []; if (!isRuntimeRecord(expectationArg) || !hasExactRuntimeKeys(expectationArg, [ 'expectationVersion', 'expectationDigest', 'reporterSessionId', 'targetAuthority', 'workloadInitAuthority', 'activeRecipient', ])) { return ['secret runtime registration expectation must use its exact schema']; } if (expectationArg.expectationVersion !== 2) { errors.push('secret runtime registration expectationVersion must be 2'); } if (!isRuntimeIdentifier(expectationArg.reporterSessionId)) { errors.push('expected secret runtime reporterSessionId must be canonical'); } const targetAuthorityErrors = await validateClusterRuntimeTargetSet( expectationArg.targetAuthority, ); errors.push(...targetAuthorityErrors.map((errorArg) => `expected ${errorArg}`)); if (targetAuthorityErrors.length === 0 && !isClusterRuntimeTargetSetFresh( expectationArg.targetAuthority as IClusterRuntimeTargetSetReadyV1, trustedNowArg, )) { errors.push('expected cluster runtime target authority must be fresh'); } if (isRuntimeRecord(expectationArg.targetAuthority) && expectationArg.targetAuthority.state === 'ready') { errors.push(...validateRuntimeTargets( expectationArg.targetAuthority.targets, 'expected targets', )); } errors.push(...await validateWorkloadInitActiveApprovalAuthority( expectationArg.workloadInitAuthority, )); const expectedRecipientErrors = validateSecretRecipientMetadata(expectationArg.activeRecipient); if (expectedRecipientErrors.length > 0 || !isRuntimeRecord(expectationArg.activeRecipient) || expectationArg.activeRecipient.lifecycleState !== 'active') { errors.push('expected secret recipient must be canonical and active'); } if (isRuntimeRecord(expectationArg.workloadInitAuthority) && isRuntimeRecord(expectationArg.workloadInitAuthority.approval) && Array.isArray(expectationArg.workloadInitAuthority.approval.artifacts) && isRuntimeRecord(expectationArg.targetAuthority) && Array.isArray(expectationArg.targetAuthority.targets)) { const approvedPlatforms = new Set( expectationArg.workloadInitAuthority.approval.artifacts.map((artifactArg) => ( isRuntimeRecord(artifactArg) ? artifactArg.platform : undefined )), ); if (expectationArg.targetAuthority.targets.some((targetArg) => ( !isRuntimeRecord(targetArg) || !approvedPlatforms.has(targetArg.platform) ))) { errors.push('expected target platforms must all have approved WorkloadInit artifacts'); } } if (typeof expectationArg.expectationDigest !== 'string' || !isSha256Digest(expectationArg.expectationDigest)) { errors.push('secret runtime expectationDigest must be canonical'); } else if (errors.length === 0 && expectationArg.expectationDigest !== await computeCoreflowSecretRuntimeRegistrationExpectationDigest( expectationArg as unknown as ICoreflowSecretRuntimeRegistrationExpectationV2, )) { errors.push('secret runtime expectationDigest does not match'); } return errors; } catch { return ['secret runtime registration expectation must be safely inspectable']; } }; /** * Consumers discard this registration on transport disconnect, tag * removal/replacement, reporter-session change, or any expectation change. */ export const validateCoreflowSecretRuntimeRegistration = async ( registrationArg: unknown, expectationArg: unknown, trustedNowArg: number, ): Promise => { try { const errors = await validateCoreflowSecretRuntimeRegistrationExpectation( expectationArg, trustedNowArg, ); if (errors.length > 0 || !isRuntimeRecord(expectationArg)) return errors; if (!isRuntimeRecord(registrationArg) || !hasExactRuntimeKeys(registrationArg, [ 'registrationVersion', 'expectationDigest', 'reporterSessionId', 'registeredAt', 'targetGeneration', 'targetSetDigest', 'targets', 'nodeEvidence', 'capabilities', 'activeRecipient', 'workloadInitAuthority', 'workloadInitImageIndexDigest', ])) { errors.push('secret runtime registration must use its exact schema'); return errors; } if (registrationArg.registrationVersion !== 2) { errors.push('secret runtime registrationVersion must be 2'); } if (registrationArg.expectationDigest !== expectationArg.expectationDigest) { errors.push('secret runtime registration expectationDigest does not match'); } if (!isRuntimeIdentifier(registrationArg.reporterSessionId)) { errors.push('secret runtime reporterSessionId must be canonical'); } else if (registrationArg.reporterSessionId !== expectationArg.reporterSessionId) { errors.push('secret runtime reporterSessionId does not match the live session'); } if (!isPositiveSafeInteger(registrationArg.registeredAt)) { errors.push('secret runtime registration timestamp must be positive'); } const registrationTargetErrors = validateRuntimeTargets( registrationArg.targets, 'registration targets', ); errors.push(...registrationTargetErrors); const targetAuthority = expectationArg.targetAuthority as unknown as IClusterRuntimeTargetSetReadyV1; if (registrationArg.targetGeneration !== targetAuthority.generation || registrationArg.targetSetDigest !== targetAuthority.targetSetDigest) { errors.push('secret runtime registration target authority does not match'); } if (typeof registrationArg.workloadInitImageIndexDigest !== 'string' || !isSha256Digest(registrationArg.workloadInitImageIndexDigest)) { errors.push('secret runtime WorkloadInit image index digest must be canonical'); } const registrationRecipientErrors = validateSecretRecipientMetadata(registrationArg.activeRecipient); const expectedRecipientErrors = validateSecretRecipientMetadata(expectationArg.activeRecipient); if (registrationRecipientErrors.length > 0 || !isRuntimeRecord(registrationArg.activeRecipient) || registrationArg.activeRecipient.lifecycleState !== 'active') { errors.push('secret runtime registration recipient must be canonical and active'); } const registrationAuthorityErrors = validateWorkloadInitApprovalAuthorityReference( registrationArg.workloadInitAuthority, ); errors.push(...registrationAuthorityErrors); if (!isRuntimeRecord(registrationArg.capabilities) || !hasOnlyRuntimeKeys(registrationArg.capabilities, [ 'immutableImageDeploymentVersion', 'corestoreInventoryVersion', 'secretManifestVersion', 'sealedSecretMaterialVersion', 'secretRecipientEnrollmentVersion', 'workloadInitEnvironmentVersion', 'secretDeploymentReportVersion', ]) || registrationArg.capabilities.immutableImageDeploymentVersion !== 1 || registrationArg.capabilities.secretManifestVersion !== 2 || registrationArg.capabilities.sealedSecretMaterialVersion !== 1 || registrationArg.capabilities.secretRecipientEnrollmentVersion !== 1 || registrationArg.capabilities.workloadInitEnvironmentVersion !== 1 || registrationArg.capabilities.secretDeploymentReportVersion !== 1 || (registrationArg.capabilities.corestoreInventoryVersion !== undefined && registrationArg.capabilities.corestoreInventoryVersion !== 1)) { errors.push('secret runtime registration capabilities are incomplete or unsupported'); } if (!Array.isArray(registrationArg.nodeEvidence) || registrationArg.nodeEvidence.length === 0 || registrationArg.nodeEvidence.length > maximumRuntimeNodes) { errors.push('secret runtime node evidence must be a non-empty bounded array'); } else { const evidenceTargets: ICoreflowSecretRuntimeNodeTargetV2[] = []; const evidenceArtifacts: IWorkloadInitApprovedArtifactV1[] = []; for (const [index, evidenceArg] of registrationArg.nodeEvidence.entries()) { if (!isRuntimeRecord(evidenceArg) || !hasExactRuntimeKeys(evidenceArg, [ 'cloudlyNodeId', 'swarmClusterId', 'swarmNodeId', 'nodeName', 'platform', 'workloadInitPlatformManifestDigest', 'workloadInitExecutableDigest', ])) { errors.push(`secret runtime nodeEvidence[${index}] must use its exact schema`); continue; } evidenceTargets.push({ cloudlyNodeId: evidenceArg.cloudlyNodeId as string, swarmClusterId: evidenceArg.swarmClusterId as string, swarmNodeId: evidenceArg.swarmNodeId as string, nodeName: evidenceArg.nodeName as string, platform: evidenceArg.platform as TImmutableContainerPlatform, }); evidenceArtifacts.push({ platform: evidenceArg.platform as TImmutableContainerPlatform, workloadInitPlatformManifestDigest: evidenceArg.workloadInitPlatformManifestDigest as TSha256Digest, workloadInitExecutableDigest: evidenceArg.workloadInitExecutableDigest as TSha256Digest, }); if (typeof evidenceArg.workloadInitPlatformManifestDigest !== 'string' || !isSha256Digest(evidenceArg.workloadInitPlatformManifestDigest) || typeof evidenceArg.workloadInitExecutableDigest !== 'string' || !isSha256Digest(evidenceArg.workloadInitExecutableDigest)) { errors.push(`secret runtime nodeEvidence[${index}] digests must be canonical`); } } errors.push(...validateRuntimeTargets(evidenceTargets, 'secret runtime evidence targets')); if (JSON.stringify(evidenceTargets) !== JSON.stringify(registrationArg.targets)) { errors.push('secret runtime node evidence must exactly cover registration targets in order'); } const expectedArtifacts = new Map< TImmutableContainerPlatform, IWorkloadInitApprovedArtifactV1 >(((expectationArg.workloadInitAuthority as unknown as IWorkloadInitActiveApprovalAuthorityV1) .approval.artifacts) .map((artifactArg) => [artifactArg.platform, artifactArg])); for (const [index, artifactArg] of evidenceArtifacts.entries()) { const expectedArtifact = expectedArtifacts.get(artifactArg.platform); if (!expectedArtifact || expectedArtifact.workloadInitPlatformManifestDigest !== artifactArg.workloadInitPlatformManifestDigest || expectedArtifact.workloadInitExecutableDigest !== artifactArg.workloadInitExecutableDigest) { errors.push(`secret runtime nodeEvidence[${index}] does not match the approved artifact`); } } } if (JSON.stringify(registrationArg.targets) !== JSON.stringify(targetAuthority.targets)) { errors.push('secret runtime registration must exactly cover authoritative target nodes'); } const workloadInitAuthority = expectationArg.workloadInitAuthority as IWorkloadInitActiveApprovalAuthorityV1; if (registrationArg.workloadInitImageIndexDigest !== workloadInitAuthority.approval.workloadInitImageIndexDigest) { errors.push('secret runtime WorkloadInit image index is not approved'); } if (isRuntimeRecord(registrationArg.workloadInitAuthority) && ( registrationArg.workloadInitAuthority.authorityVersion !== workloadInitAuthority.authorityVersion || registrationArg.workloadInitAuthority.authorityGeneration !== workloadInitAuthority.authorityGeneration || registrationArg.workloadInitAuthority.approvalDigest !== workloadInitAuthority.approvalDigest )) { errors.push('secret runtime WorkloadInit authority does not match'); } if (registrationRecipientErrors.length === 0 && expectedRecipientErrors.length === 0 && activeRecipientFingerprint( registrationArg.activeRecipient as unknown as IActiveSecretRecipientMetadata, ) !== activeRecipientFingerprint( expectationArg.activeRecipient as unknown as IActiveSecretRecipientMetadata, )) { errors.push('secret runtime registration recipient does not match the active recipient'); } return errors; } catch { return ['secret runtime registration and expectation must be safely inspectable']; } }; interface ISecretDeploymentReportBaseV1 { schemaVersion: 1; reporterSessionId: string; reportSequence: number; serviceId: string; expectedPlanRevision: number; desiredManifest: IResolvedSecretManifestReference; reportedAt: number; reportDigest: TSha256Digest; } export interface ISecretDeploymentApplyingReportV1 extends ISecretDeploymentReportBaseV1 { status: 'applying'; } export interface ISecretDeploymentAppliedReportV1 extends ISecretDeploymentReportBaseV1 { status: 'applied'; appliedManifest: IResolvedSecretManifestReference; } export interface ISecretDeploymentDriftedReportV1 extends ISecretDeploymentReportBaseV1 { status: 'drifted'; observedManifest?: IResolvedSecretManifestReference; failureCode: string; } export interface ISecretDeploymentFailedReportV1 extends ISecretDeploymentReportBaseV1 { status: 'failed'; failureCode: string; } export type TSecretDeploymentReportV1 = | ISecretDeploymentApplyingReportV1 | ISecretDeploymentAppliedReportV1 | ISecretDeploymentDriftedReportV1 | ISecretDeploymentFailedReportV1; export type TSecretDeploymentReportWithoutDigestV1 = | Omit | Omit | Omit | Omit; export interface ISecretDeploymentReportResponseV1 { schemaVersion: 1; acceptedSequence: number; planRevision: number; clusterState: IClusterSecretDeploymentState; } export interface IReq_ReportSecretDeploymentState extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_ReportSecretDeploymentState > { method: 'reportSecretDeploymentState'; request: TSecretDeploymentReportV1 & { identity: IIdentityCredential; }; response: ISecretDeploymentReportResponseV1; } const canonicalManifestReference = ( referenceArg: IResolvedSecretManifestReference, ): IResolvedSecretManifestReference => ({ manifestId: referenceArg.manifestId, manifestDigest: referenceArg.manifestDigest, clusterId: referenceArg.clusterId, imageRolloutId: referenceArg.imageRolloutId, imageRolloutGeneration: referenceArg.imageRolloutGeneration, requestedImageDigest: referenceArg.requestedImageDigest, invocationDigest: referenceArg.invocationDigest, secretRolloutId: referenceArg.secretRolloutId, secretRolloutGeneration: referenceArg.secretRolloutGeneration, }); export const createSecretDeploymentReportDigestInput = ( reportArg: TSecretDeploymentReportWithoutDigestV1 | TSecretDeploymentReportV1, ): string => { const common = { schemaVersion: reportArg.schemaVersion, reporterSessionId: reportArg.reporterSessionId, reportSequence: reportArg.reportSequence, serviceId: reportArg.serviceId, expectedPlanRevision: reportArg.expectedPlanRevision, desiredManifest: canonicalManifestReference(reportArg.desiredManifest), status: reportArg.status, }; if (reportArg.status === 'applied') { return JSON.stringify({ ...common, appliedManifest: canonicalManifestReference(reportArg.appliedManifest), reportedAt: reportArg.reportedAt, }); } if (reportArg.status === 'drifted') { return JSON.stringify({ ...common, ...(reportArg.observedManifest ? { observedManifest: canonicalManifestReference(reportArg.observedManifest) } : {}), failureCode: reportArg.failureCode, reportedAt: reportArg.reportedAt, }); } if (reportArg.status === 'failed') { return JSON.stringify({ ...common, failureCode: reportArg.failureCode, reportedAt: reportArg.reportedAt, }); } return JSON.stringify({ ...common, reportedAt: reportArg.reportedAt }); }; export const computeSecretDeploymentReportDigest = async ( reportArg: TSecretDeploymentReportWithoutDigestV1 | TSecretDeploymentReportV1, ): Promise => computeRuntimeSha256( createSecretDeploymentReportDigestInput(reportArg), ); export const verifySecretDeploymentReportDigest = async ( reportArg: unknown, ): Promise => { try { if (!isRuntimeRecord(reportArg) || typeof reportArg.reportDigest !== 'string' || !isSha256Digest(reportArg.reportDigest)) { return false; } return reportArg.reportDigest === await computeSecretDeploymentReportDigest( reportArg as unknown as TSecretDeploymentReportV1, ); } catch { return false; } }; /** * The expected cluster and reporter session come from the consumer's verified * live connection authority and are deliberately not accepted from the wire. */ export const validateSecretDeploymentReportRequest = async ( requestArg: unknown, expectedClusterIdArg: string, expectedReporterSessionIdArg: string, ): Promise => { try { if (!isRuntimeIdentifier(expectedClusterIdArg)) { return ['trusted expected cluster id must be canonical']; } if (!isRuntimeIdentifier(expectedReporterSessionIdArg)) { return ['trusted expected reporter session id must be canonical']; } if (!isRuntimeRecord(requestArg)) { return ['secret deployment report request must be an object']; } const status = requestArg.status; const commonKeys = [ 'identity', 'schemaVersion', 'reporterSessionId', 'reportSequence', 'serviceId', 'expectedPlanRevision', 'desiredManifest', 'status', 'reportedAt', 'reportDigest', ]; const expectedKeys = status === 'applied' ? [...commonKeys, 'appliedManifest'] : status === 'drifted' ? [...commonKeys, 'failureCode', ...(requestArg.observedManifest === undefined ? [] : ['observedManifest'])] : status === 'failed' ? [...commonKeys, 'failureCode'] : commonKeys; const errors: string[] = []; if (!['applying', 'applied', 'drifted', 'failed'].includes(status as string) || !hasExactRuntimeKeys(requestArg, expectedKeys)) { errors.push('secret deployment report must use its exact status schema'); } if (!isRuntimeRecord(requestArg.identity) || !hasExactRuntimeKeys(requestArg.identity, ['jwt']) || typeof requestArg.identity.jwt !== 'string' || requestArg.identity.jwt.length === 0) { errors.push('secret deployment report requires a JWT identity'); } if (requestArg.schemaVersion !== 1) { errors.push('secret deployment report schemaVersion must be 1'); } if (!isRuntimeIdentifier(requestArg.reporterSessionId) || !isRuntimeIdentifier(requestArg.serviceId)) { errors.push('secret deployment report identity fields must be canonical'); } else if (requestArg.reporterSessionId !== expectedReporterSessionIdArg) { errors.push('secret deployment report reporterSessionId does not match the live session'); } if (!isPositiveSafeInteger(requestArg.reportSequence) || !isPositiveSafeInteger(requestArg.expectedPlanRevision) || !isPositiveSafeInteger(requestArg.reportedAt)) { errors.push('secret deployment report revisions, sequence, and timestamp must be positive integers'); } errors.push(...validateResolvedSecretManifestReference( requestArg.desiredManifest, expectedClusterIdArg, ).map((errorArg) => `desiredManifest: ${errorArg}`)); if (status === 'applied') { errors.push(...validateResolvedSecretManifestReference( requestArg.appliedManifest, expectedClusterIdArg, ).map((errorArg) => `appliedManifest: ${errorArg}`)); if (!resolvedSecretManifestReferencesEqual( requestArg.appliedManifest as IResolvedSecretManifestReference, requestArg.desiredManifest as IResolvedSecretManifestReference, )) { errors.push('applied secret deployment report must apply the desired manifest'); } } if (status === 'drifted' && requestArg.observedManifest !== undefined) { errors.push(...validateResolvedSecretManifestReference( requestArg.observedManifest, expectedClusterIdArg, ).map((errorArg) => `observedManifest: ${errorArg}`)); } if ((status === 'drifted' || status === 'failed') && (typeof requestArg.failureCode !== 'string' || !runtimeFailureCodeRegex.test(requestArg.failureCode))) { errors.push('secret deployment report failureCode must be canonical'); } if (typeof requestArg.reportDigest !== 'string' || !isSha256Digest(requestArg.reportDigest) || !await verifySecretDeploymentReportDigest(requestArg)) { errors.push('secret deployment report digest does not match its canonical payload'); } return errors; } catch { return ['secret deployment report request must be safely inspectable']; } };