@serve.zone/interfaces 31.8.0 → 32.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/.smartconfig.json +1 -0
- package/changelog.md +512 -0
- package/dist_ts/00_commitinfo_data.js +3 -3
- package/dist_ts/appstore/types.d.ts +4 -6
- package/dist_ts/appstore/types.js +5 -5
- package/dist_ts/data/backup.d.ts +3 -26
- package/dist_ts/data/cluster.d.ts +36 -11
- package/dist_ts/data/cluster.js +33 -22
- package/dist_ts/data/clusteringress.d.ts +8 -0
- package/dist_ts/data/clusteringress.js +13 -8
- package/dist_ts/data/clusternode.d.ts +121 -74
- package/dist_ts/data/clusternode.js +109 -132
- package/dist_ts/data/clusterruntime.d.ts +39 -0
- package/dist_ts/data/clusterruntime.js +11 -0
- package/dist_ts/data/coremail.d.ts +3 -7
- package/dist_ts/data/coremail.js +2 -2
- package/dist_ts/data/coremail.runtime.d.ts +0 -1
- package/dist_ts/data/coremail.runtime.js +5 -22
- package/dist_ts/data/deploymentadoption.d.ts +0 -2
- package/dist_ts/data/deploymentadoption.js +40 -6
- package/dist_ts/data/deploymentoperation.js +16 -3
- package/dist_ts/data/deploymentpreflight.d.ts +0 -2
- package/dist_ts/data/deploymentpreflight.js +1 -1
- package/dist_ts/data/immutableimage.d.ts +38 -21
- package/dist_ts/data/immutableimage.js +45 -5
- package/dist_ts/data/index.d.ts +5 -1
- package/dist_ts/data/index.js +5 -1
- package/dist_ts/data/isolatedrestore.d.ts +139 -21
- package/dist_ts/data/isolatedrestore.golden.d.ts +0 -1
- package/dist_ts/data/isolatedrestore.golden.js +6 -9
- package/dist_ts/data/isolatedrestore.js +176 -40
- package/dist_ts/data/mail.d.ts +1 -1
- package/dist_ts/data/networkaddressplan.d.ts +78 -0
- package/dist_ts/data/networkaddressplan.js +114 -0
- package/dist_ts/data/networkauthority.d.ts +20 -22
- package/dist_ts/data/networkauthority.js +29 -43
- package/dist_ts/data/networkcredential.d.ts +10 -10
- package/dist_ts/data/networkcredential.js +16 -16
- package/dist_ts/data/networkdelivery.d.ts +18 -18
- package/dist_ts/data/networkdelivery.js +16 -16
- package/dist_ts/data/networklease.d.ts +18 -7
- package/dist_ts/data/networklease.js +29 -7
- package/dist_ts/data/networknode.d.ts +37 -0
- package/dist_ts/data/networknode.js +6 -0
- package/dist_ts/data/networkprojection.d.ts +59 -60
- package/dist_ts/data/networkprojection.js +53 -57
- package/dist_ts/data/networkprotection.d.ts +27 -28
- package/dist_ts/data/networkprotection.js +36 -36
- package/dist_ts/data/networkrouter.d.ts +11 -11
- package/dist_ts/data/networkrouter.js +1 -1
- package/dist_ts/data/networksigning.d.ts +16 -18
- package/dist_ts/data/networksigning.js +20 -21
- package/dist_ts/data/nodecredential.d.ts +4 -6
- package/dist_ts/data/nodeenrollment.d.ts +35 -40
- package/dist_ts/data/nodeenrollment.js +57 -72
- package/dist_ts/data/privatenetwork.d.ts +21 -24
- package/dist_ts/data/privatenetwork.js +39 -54
- package/dist_ts/data/runtimeassignment.d.ts +50 -34
- package/dist_ts/data/runtimeassignment.js +79 -45
- package/dist_ts/data/runtimeconfig.d.ts +21 -22
- package/dist_ts/data/runtimeconfig.js +37 -100
- package/dist_ts/data/runtimesession.d.ts +100 -62
- package/dist_ts/data/runtimesession.js +98 -79
- package/dist_ts/data/runtimeterminalreceipt.d.ts +28 -29
- package/dist_ts/data/runtimeterminalreceipt.js +42 -42
- package/dist_ts/data/secret.d.ts +18 -25
- package/dist_ts/data/secret.js +12 -52
- package/dist_ts/data/servicecredential.d.ts +14 -16
- package/dist_ts/data/servicecredential.js +17 -28
- package/dist_ts/data/serviceruntime.d.ts +128 -0
- package/dist_ts/data/serviceruntime.js +92 -0
- package/dist_ts/data/sparknodereport.d.ts +27 -14
- package/dist_ts/data/sparknodereport.js +35 -28
- package/dist_ts/data/webpush.d.ts +0 -1
- package/dist_ts/index.d.ts +2 -1
- package/dist_ts/index.js +3 -2
- package/dist_ts/platform/objectstorageretention.d.ts +21 -24
- package/dist_ts/platform/objectstorageretention.js +6 -18
- package/dist_ts/platform/storage.d.ts +1 -3
- package/dist_ts/platform/storagemigration.d.ts +0 -7
- package/dist_ts/platform/storagemigration.golden.d.ts +0 -1
- package/dist_ts/platform/storagemigration.golden.js +8 -12
- package/dist_ts/platform/storagemigration.js +6 -51
- package/dist_ts/platform/types.d.ts +2 -2
- package/dist_ts/private/canonicaljson.d.ts +9 -1
- package/dist_ts/private/canonicaljson.js +14 -2
- package/dist_ts/private/dataproperties.d.ts +62 -0
- package/dist_ts/private/dataproperties.js +117 -0
- package/dist_ts/private/networkcontract.d.ts +14 -10
- package/dist_ts/private/networkcontract.js +15 -1
- package/dist_ts/private/producercontract.d.ts +11 -0
- package/dist_ts/private/producercontract.js +21 -0
- package/dist_ts/private/releaseversion.d.ts +37 -0
- package/dist_ts/private/releaseversion.js +48 -0
- package/dist_ts/private/runtimepolicy.d.ts +31 -0
- package/dist_ts/private/runtimepolicy.js +90 -0
- package/dist_ts/private/tokenlist.d.ts +9 -0
- package/dist_ts/private/tokenlist.js +23 -0
- package/dist_ts/protocol.d.ts +137 -0
- package/dist_ts/protocol.js +255 -0
- package/dist_ts/requests/admin.d.ts +8 -8
- package/dist_ts/requests/backup.d.ts +102 -112
- package/dist_ts/requests/cluster.d.ts +47 -10
- package/dist_ts/requests/cluster.js +1 -1
- package/dist_ts/requests/clusteringress.d.ts +9 -0
- package/dist_ts/requests/clusteringress.js +1 -1
- package/dist_ts/requests/config.d.ts +3 -3
- package/dist_ts/requests/corestore.d.ts +0 -3
- package/dist_ts/requests/corestore.js +5 -9
- package/dist_ts/requests/network.d.ts +87 -31
- package/dist_ts/requests/node.d.ts +15 -28
- package/dist_ts/requests/pallet.d.ts +13 -13
- package/dist_ts/requests/runtimesession.d.ts +53 -41
- package/dist_ts/requests/secret.d.ts +4 -5
- package/dist_ts/requests/secret.js +1 -5
- package/dist_ts/requests/service.d.ts +60 -0
- package/dist_ts/runtime.corestore.d.ts +56 -74
- package/dist_ts/runtime.corestore.databaseexportpackage.d.ts +30 -36
- package/dist_ts/runtime.corestore.databaseexportpackage.golden.d.ts +11 -12
- package/dist_ts/runtime.corestore.databaseexportpackage.golden.js +54 -71
- package/dist_ts/runtime.corestore.databaseexportpackage.js +9 -25
- package/dist_ts/runtime.corestore.js +35 -135
- package/dist_ts/runtime.corestore.relay.js +2 -7
- package/dist_ts/runtime.d.ts +38 -48
- package/dist_ts/runtime.js +20 -77
- package/dist_ts/runtime.networkprojection.d.ts +4 -4
- package/dist_ts/runtime.networkprojection.js +18 -18
- package/dist_ts/runtime.workloadinit.d.ts +23 -24
- package/dist_ts/runtime.workloadinit.js +6 -13
- package/package.json +2 -2
- package/readme.md +540 -269
- package/ts/00_commitinfo_data.ts +3 -3
- package/ts/appstore/types.ts +4 -6
- package/ts/data/backup.ts +3 -38
- package/ts/data/cluster.ts +51 -34
- package/ts/data/clusteringress.ts +12 -12
- package/ts/data/clusternode.ts +204 -232
- package/ts/data/clusterruntime.ts +45 -0
- package/ts/data/coremail.runtime.ts +4 -21
- package/ts/data/coremail.ts +3 -7
- package/ts/data/deploymentadoption.ts +46 -4
- package/ts/data/deploymentoperation.ts +16 -1
- package/ts/data/deploymentpreflight.ts +0 -2
- package/ts/data/immutableimage.ts +71 -24
- package/ts/data/index.ts +5 -1
- package/ts/data/isolatedrestore.golden.ts +5 -9
- package/ts/data/isolatedrestore.ts +339 -54
- package/ts/data/mail.ts +1 -1
- package/ts/data/networkaddressplan.ts +175 -0
- package/ts/data/networkauthority.ts +45 -61
- package/ts/data/networkcredential.ts +24 -24
- package/ts/data/networkdelivery.ts +27 -27
- package/ts/data/networklease.ts +40 -13
- package/ts/data/networknode.ts +37 -0
- package/ts/data/networkprojection.ts +119 -124
- package/ts/data/networkprotection.ts +54 -55
- package/ts/data/networkrouter.ts +14 -14
- package/ts/data/networksigning.ts +29 -32
- package/ts/data/nodecredential.ts +4 -6
- package/ts/data/nodeenrollment.ts +96 -114
- package/ts/data/privatenetwork.ts +58 -74
- package/ts/data/runtimeassignment.ts +143 -94
- package/ts/data/runtimeconfig.ts +62 -122
- package/ts/data/runtimesession.ts +185 -138
- package/ts/data/runtimeterminalreceipt.ts +72 -73
- package/ts/data/secret.ts +28 -76
- package/ts/data/servicecredential.ts +33 -43
- package/ts/data/serviceruntime.ts +208 -0
- package/ts/data/sparknodereport.ts +48 -36
- package/ts/data/webpush.ts +0 -1
- package/ts/index.ts +2 -0
- package/ts/platform/objectstorageretention.ts +36 -55
- package/ts/platform/storage.ts +1 -3
- package/ts/platform/storagemigration.golden.ts +7 -11
- package/ts/platform/storagemigration.ts +5 -55
- package/ts/platform/types.ts +2 -2
- package/ts/private/canonicaljson.ts +13 -1
- package/ts/private/dataproperties.ts +139 -0
- package/ts/private/networkcontract.ts +23 -9
- package/ts/private/producercontract.ts +19 -0
- package/ts/private/releaseversion.ts +70 -0
- package/ts/private/runtimepolicy.ts +105 -0
- package/ts/private/tokenlist.ts +30 -0
- package/ts/protocol.ts +364 -0
- package/ts/requests/admin.ts +11 -11
- package/ts/requests/backup.ts +112 -117
- package/ts/requests/cluster.ts +58 -13
- package/ts/requests/clusteringress.ts +9 -0
- package/ts/requests/config.ts +3 -3
- package/ts/requests/corestore.ts +4 -16
- package/ts/requests/network.ts +90 -41
- package/ts/requests/node.ts +21 -38
- package/ts/requests/pallet.ts +17 -17
- package/ts/requests/runtimesession.ts +63 -51
- package/ts/requests/secret.ts +5 -10
- package/ts/requests/service.ts +81 -0
- package/ts/runtime.corestore.databaseexportpackage.golden.ts +77 -95
- package/ts/runtime.corestore.databaseexportpackage.ts +51 -73
- package/ts/runtime.corestore.relay.ts +1 -10
- package/ts/runtime.corestore.ts +118 -268
- package/ts/runtime.networkprojection.ts +30 -30
- package/ts/runtime.ts +83 -158
- package/ts/runtime.workloadinit.ts +36 -48
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.d.ts +0 -902
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.golden.d.ts +0 -35
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.golden.js +0 -315
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.js +0 -3315
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.d.ts +0 -291
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.d.ts +0 -30
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.js +0 -408
- package/dist_ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.js +0 -1126
- package/ts/runtime.cloudlylegacydeploymentsettlement.golden.ts +0 -421
- package/ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.golden.ts +0 -510
- package/ts/runtime.cloudlylegacydeploymentsettlement.offlineexport.ts +0 -2470
- package/ts/runtime.cloudlylegacydeploymentsettlement.ts +0 -6630
package/ts/data/secret.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as plugins from '../plugins.js';
|
|
2
2
|
import type { TSha256Digest } from './immutableimage.js';
|
|
3
3
|
import { normalizeServiceAbsolutePath } from './service.js';
|
|
4
|
+
import { hasExactKeys } from '../private/dataproperties.js';
|
|
4
5
|
|
|
5
6
|
export type TSecretEnvironment = string;
|
|
6
7
|
|
|
@@ -135,8 +136,7 @@ export interface ISecretVersionMetadata {
|
|
|
135
136
|
}
|
|
136
137
|
|
|
137
138
|
/** Irreversibly erases every platform-managed copy after all references are gone. */
|
|
138
|
-
export interface
|
|
139
|
-
schemaVersion: 1;
|
|
139
|
+
export interface ISecretVersionPurgeIntent {
|
|
140
140
|
mutationId: string;
|
|
141
141
|
secretId: string;
|
|
142
142
|
secretVersionId: string;
|
|
@@ -145,34 +145,33 @@ export interface ISecretVersionPurgeIntentV1 {
|
|
|
145
145
|
expectedTargetSecretsRevision: number;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
export interface
|
|
148
|
+
export interface ISecretVersionPurgeFailure {
|
|
149
149
|
code: string;
|
|
150
150
|
retryable: boolean;
|
|
151
151
|
failedAt: number;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
interface
|
|
155
|
-
schemaVersion: 1;
|
|
154
|
+
interface ISecretVersionPurgeOperationBase {
|
|
156
155
|
id: string;
|
|
157
156
|
revision: number;
|
|
158
|
-
intent:
|
|
157
|
+
intent: ISecretVersionPurgeIntent;
|
|
159
158
|
intentDigest: TSha256Digest;
|
|
160
159
|
createdAt: number;
|
|
161
160
|
updatedAt: number;
|
|
162
161
|
}
|
|
163
162
|
|
|
164
|
-
export type
|
|
165
|
-
| (
|
|
163
|
+
export type TSecretVersionPurgeOperation =
|
|
164
|
+
| (ISecretVersionPurgeOperationBase & {
|
|
166
165
|
state: 'pending' | 'erasing';
|
|
167
166
|
failure?: never;
|
|
168
167
|
purgedAt?: never;
|
|
169
168
|
})
|
|
170
|
-
| (
|
|
169
|
+
| (ISecretVersionPurgeOperationBase & {
|
|
171
170
|
state: 'failed';
|
|
172
|
-
failure:
|
|
171
|
+
failure: ISecretVersionPurgeFailure;
|
|
173
172
|
purgedAt?: never;
|
|
174
173
|
})
|
|
175
|
-
| (
|
|
174
|
+
| (ISecretVersionPurgeOperationBase & {
|
|
176
175
|
state: 'succeeded';
|
|
177
176
|
failure?: never;
|
|
178
177
|
purgedAt: number;
|
|
@@ -275,7 +274,6 @@ export interface ISecretSetAttachment {
|
|
|
275
274
|
* Cloudly verifies organization ownership when resolving the referenced sets.
|
|
276
275
|
*/
|
|
277
276
|
export interface IServiceSecretConfiguration {
|
|
278
|
-
schemaVersion: 2;
|
|
279
277
|
/** Dedicated CAS revision for SecretSet attachments. */
|
|
280
278
|
revision: number;
|
|
281
279
|
/** Dedicated CAS revision for service-owned secret membership. */
|
|
@@ -294,7 +292,6 @@ export interface IResolvedSecretManifestEntry {
|
|
|
294
292
|
|
|
295
293
|
/** Immutable, value-free runtime snapshot. */
|
|
296
294
|
export interface IResolvedSecretManifest {
|
|
297
|
-
schemaVersion: 2;
|
|
298
295
|
id: string;
|
|
299
296
|
digest: TSha256Digest;
|
|
300
297
|
organizationId: string;
|
|
@@ -346,7 +343,6 @@ export interface IClusterSecretDeploymentState {
|
|
|
346
343
|
|
|
347
344
|
/** Server-managed per-cluster authority switched with an expected revision CAS. */
|
|
348
345
|
export interface IServiceSecretDeploymentPlan {
|
|
349
|
-
schemaVersion: 2;
|
|
350
346
|
revision: number;
|
|
351
347
|
clusterStates: IClusterSecretDeploymentState[];
|
|
352
348
|
updatedAt: number;
|
|
@@ -395,15 +391,6 @@ const isRecord = (valueArg: unknown): valueArg is Record<string, unknown> => (
|
|
|
395
391
|
Boolean(valueArg) && typeof valueArg === 'object' && !Array.isArray(valueArg)
|
|
396
392
|
);
|
|
397
393
|
|
|
398
|
-
const hasExactKeys = (
|
|
399
|
-
valueArg: Record<string, unknown>,
|
|
400
|
-
keysArg: string[],
|
|
401
|
-
): boolean => {
|
|
402
|
-
const actual = Object.keys(valueArg).sort();
|
|
403
|
-
const expected = [...keysArg].sort();
|
|
404
|
-
return JSON.stringify(actual) === JSON.stringify(expected);
|
|
405
|
-
};
|
|
406
|
-
|
|
407
394
|
const hasOnlyKeys = (
|
|
408
395
|
valueArg: Record<string, unknown>,
|
|
409
396
|
keysArg: string[],
|
|
@@ -536,7 +523,6 @@ export const validateSecretVersionPurgeIntent = (
|
|
|
536
523
|
): string[] => {
|
|
537
524
|
if (!isRecord(intentArg)
|
|
538
525
|
|| !hasExactKeys(intentArg, [
|
|
539
|
-
'schemaVersion',
|
|
540
526
|
'mutationId',
|
|
541
527
|
'secretId',
|
|
542
528
|
'secretVersionId',
|
|
@@ -547,9 +533,6 @@ export const validateSecretVersionPurgeIntent = (
|
|
|
547
533
|
return ['secret version purge intent must use its exact schema'];
|
|
548
534
|
}
|
|
549
535
|
const errors = validateSecretMutationId(intentArg.mutationId);
|
|
550
|
-
if (intentArg.schemaVersion !== 1) {
|
|
551
|
-
errors.push('secret version purge intent schemaVersion must be 1');
|
|
552
|
-
}
|
|
553
536
|
for (const field of ['secretId', 'secretVersionId'] as const) {
|
|
554
537
|
if (!isSecretIdentifier(intentArg[field])) {
|
|
555
538
|
errors.push(`secret version purge intent ${field} must be canonical`);
|
|
@@ -567,9 +550,8 @@ export const validateSecretVersionPurgeIntent = (
|
|
|
567
550
|
};
|
|
568
551
|
|
|
569
552
|
export const createSecretVersionPurgeIntentDigestInput = (
|
|
570
|
-
intentArg:
|
|
553
|
+
intentArg: ISecretVersionPurgeIntent,
|
|
571
554
|
): string => JSON.stringify({
|
|
572
|
-
schemaVersion: intentArg.schemaVersion,
|
|
573
555
|
purpose: 'serve.zone/secret-version-purge',
|
|
574
556
|
mutationId: intentArg.mutationId,
|
|
575
557
|
secretId: intentArg.secretId,
|
|
@@ -580,7 +562,7 @@ export const createSecretVersionPurgeIntentDigestInput = (
|
|
|
580
562
|
});
|
|
581
563
|
|
|
582
564
|
export const computeSecretVersionPurgeIntentDigest = async (
|
|
583
|
-
intentArg:
|
|
565
|
+
intentArg: ISecretVersionPurgeIntent,
|
|
584
566
|
): Promise<TSha256Digest> => {
|
|
585
567
|
if (validateSecretVersionPurgeIntent(intentArg).length > 0) {
|
|
586
568
|
throw new Error('secret version purge intent must be canonical');
|
|
@@ -595,7 +577,7 @@ export const computeSecretVersionPurgeIntentDigest = async (
|
|
|
595
577
|
};
|
|
596
578
|
|
|
597
579
|
export const verifySecretVersionPurgeIntentDigest = async (
|
|
598
|
-
intentArg:
|
|
580
|
+
intentArg: ISecretVersionPurgeIntent,
|
|
599
581
|
digestArg: unknown,
|
|
600
582
|
): Promise<boolean> => {
|
|
601
583
|
try {
|
|
@@ -613,27 +595,15 @@ export const validateSecretVersionPurgeOperation = async (
|
|
|
613
595
|
if (!isRecord(operationArg)) return ['secret version purge operation must be an object'];
|
|
614
596
|
const state = operationArg.state;
|
|
615
597
|
const expectedKeys = state === 'failed'
|
|
616
|
-
? [
|
|
617
|
-
'schemaVersion', 'id', 'revision', 'intent', 'intentDigest', 'state',
|
|
618
|
-
'failure', 'createdAt', 'updatedAt',
|
|
619
|
-
]
|
|
598
|
+
? ['id', 'revision', 'intent', 'intentDigest', 'state', 'failure', 'createdAt', 'updatedAt']
|
|
620
599
|
: state === 'succeeded'
|
|
621
|
-
? [
|
|
622
|
-
|
|
623
|
-
'purgedAt', 'createdAt', 'updatedAt',
|
|
624
|
-
]
|
|
625
|
-
: [
|
|
626
|
-
'schemaVersion', 'id', 'revision', 'intent', 'intentDigest', 'state',
|
|
627
|
-
'createdAt', 'updatedAt',
|
|
628
|
-
];
|
|
600
|
+
? ['id', 'revision', 'intent', 'intentDigest', 'state', 'purgedAt', 'createdAt', 'updatedAt']
|
|
601
|
+
: ['id', 'revision', 'intent', 'intentDigest', 'state', 'createdAt', 'updatedAt'];
|
|
629
602
|
if (!['pending', 'erasing', 'failed', 'succeeded'].includes(state as string)
|
|
630
603
|
|| !hasExactKeys(operationArg, expectedKeys)) {
|
|
631
604
|
return ['secret version purge operation must use its exact state schema'];
|
|
632
605
|
}
|
|
633
606
|
const errors = validateSecretVersionPurgeIntent(operationArg.intent);
|
|
634
|
-
if (operationArg.schemaVersion !== 1) {
|
|
635
|
-
errors.push('secret version purge operation schemaVersion must be 1');
|
|
636
|
-
}
|
|
637
607
|
if (!isSecretIdentifier(operationArg.id) || !isPositiveSafeInteger(operationArg.revision)) {
|
|
638
608
|
errors.push('secret version purge operation identity and revision must be canonical');
|
|
639
609
|
}
|
|
@@ -647,7 +617,7 @@ export const validateSecretVersionPurgeOperation = async (
|
|
|
647
617
|
&& secretDigestRegex.test(operationArg.intentDigest)) {
|
|
648
618
|
try {
|
|
649
619
|
if (!await verifySecretVersionPurgeIntentDigest(
|
|
650
|
-
operationArg.intent as unknown as
|
|
620
|
+
operationArg.intent as unknown as ISecretVersionPurgeIntent,
|
|
651
621
|
operationArg.intentDigest,
|
|
652
622
|
)) {
|
|
653
623
|
errors.push('secret version purge operation intentDigest does not match');
|
|
@@ -964,16 +934,12 @@ export const validateServiceSecretConfiguration = (
|
|
|
964
934
|
}
|
|
965
935
|
const errors: string[] = [];
|
|
966
936
|
if (!hasExactKeys(configurationArg, [
|
|
967
|
-
'schemaVersion',
|
|
968
937
|
'revision',
|
|
969
938
|
'secretsRevision',
|
|
970
939
|
'secretSetAttachments',
|
|
971
940
|
])) {
|
|
972
941
|
errors.push('secretConfiguration must use its exact schema');
|
|
973
942
|
}
|
|
974
|
-
if (configurationArg.schemaVersion !== 2) {
|
|
975
|
-
errors.push('secretConfiguration schemaVersion must be 2');
|
|
976
|
-
}
|
|
977
943
|
if (!Array.isArray(configurationArg.secretSetAttachments)) {
|
|
978
944
|
errors.push('secretSetAttachments must be an array');
|
|
979
945
|
return errors;
|
|
@@ -1103,7 +1069,6 @@ export const validateSecretSetAttachmentOwnership = (
|
|
|
1103
1069
|
export const createResolvedSecretManifestDigestInput = (
|
|
1104
1070
|
manifestArg: IResolvedSecretManifest,
|
|
1105
1071
|
): string => JSON.stringify({
|
|
1106
|
-
schemaVersion: manifestArg.schemaVersion,
|
|
1107
1072
|
id: manifestArg.id,
|
|
1108
1073
|
organizationId: manifestArg.organizationId,
|
|
1109
1074
|
serviceId: manifestArg.serviceId,
|
|
@@ -1171,7 +1136,6 @@ export const validateResolvedSecretManifest = (
|
|
|
1171
1136
|
if (!isRecord(manifestArg)) return ['secret manifest must be an object'];
|
|
1172
1137
|
const errors: string[] = [];
|
|
1173
1138
|
if (!hasExactKeys(manifestArg, [
|
|
1174
|
-
'schemaVersion',
|
|
1175
1139
|
'id',
|
|
1176
1140
|
'digest',
|
|
1177
1141
|
'organizationId',
|
|
@@ -1188,7 +1152,6 @@ export const validateResolvedSecretManifest = (
|
|
|
1188
1152
|
])) {
|
|
1189
1153
|
errors.push('secret manifest must use its exact schema');
|
|
1190
1154
|
}
|
|
1191
|
-
if (manifestArg.schemaVersion !== 2) errors.push('secret manifest schemaVersion must be 2');
|
|
1192
1155
|
for (const field of [
|
|
1193
1156
|
'id',
|
|
1194
1157
|
'organizationId',
|
|
@@ -1397,14 +1360,12 @@ export const validateServiceSecretDeploymentPlan = (
|
|
|
1397
1360
|
if (!isRecord(planArg)) return ['secret deployment plan must be an object'];
|
|
1398
1361
|
const errors: string[] = [];
|
|
1399
1362
|
if (!hasExactKeys(planArg, [
|
|
1400
|
-
'schemaVersion',
|
|
1401
1363
|
'revision',
|
|
1402
1364
|
'clusterStates',
|
|
1403
1365
|
'updatedAt',
|
|
1404
1366
|
])) {
|
|
1405
1367
|
errors.push('secret deployment plan must use its exact schema');
|
|
1406
1368
|
}
|
|
1407
|
-
if (planArg.schemaVersion !== 2) errors.push('secret deployment plan schemaVersion must be 2');
|
|
1408
1369
|
if (!Number.isSafeInteger(planArg.revision) || (planArg.revision as number) < 1) {
|
|
1409
1370
|
errors.push('secret deployment plan revision must be a positive integer');
|
|
1410
1371
|
}
|
|
@@ -1528,11 +1489,11 @@ export const validateServiceSecretDeploymentPlan = (
|
|
|
1528
1489
|
return errors;
|
|
1529
1490
|
};
|
|
1530
1491
|
|
|
1531
|
-
export const dockerSecretResourceNameDomain = 'serve.zone/docker-secret-resource
|
|
1532
|
-
export const workloadInitEnvironmentMapPath = '/run/serve.zone/workloadinit-map
|
|
1492
|
+
export const dockerSecretResourceNameDomain = 'serve.zone/docker-secret-resource' as const;
|
|
1493
|
+
export const workloadInitEnvironmentMapPath = '/run/serve.zone/workloadinit-map.json' as const;
|
|
1533
1494
|
export const workloadRuntimeAssetRoot = '/opt/serve.zone/runtime-assets' as const;
|
|
1534
1495
|
export const workloadInitExecutablePath =
|
|
1535
|
-
'/opt/serve.zone/runtime-assets/workloadinit/
|
|
1496
|
+
'/opt/serve.zone/runtime-assets/workloadinit/workloadinit' as const;
|
|
1536
1497
|
export const workloadInitEnvironmentMapMode = 0o444 as const;
|
|
1537
1498
|
export const workloadRuntimeAssetsReadOnly = true as const;
|
|
1538
1499
|
|
|
@@ -1579,17 +1540,16 @@ export const createLauncherSecretSourcePath = (
|
|
|
1579
1540
|
return `/run/serve.zone/secrets/${resourceArg}`;
|
|
1580
1541
|
};
|
|
1581
1542
|
|
|
1582
|
-
export interface
|
|
1543
|
+
export interface IWorkloadInitEnvironmentMapEntry {
|
|
1583
1544
|
variableName: string;
|
|
1584
1545
|
resource: string;
|
|
1585
1546
|
source: string;
|
|
1586
1547
|
}
|
|
1587
1548
|
|
|
1588
|
-
export interface
|
|
1589
|
-
schemaVersion: 1;
|
|
1549
|
+
export interface IWorkloadInitEnvironmentMap {
|
|
1590
1550
|
manifestId: string;
|
|
1591
1551
|
manifestDigest: TSha256Digest;
|
|
1592
|
-
entries:
|
|
1552
|
+
entries: IWorkloadInitEnvironmentMapEntry[];
|
|
1593
1553
|
}
|
|
1594
1554
|
|
|
1595
1555
|
/**
|
|
@@ -1600,7 +1560,7 @@ export interface IWorkloadInitEnvironmentMapV1 {
|
|
|
1600
1560
|
*/
|
|
1601
1561
|
export const createWorkloadInitEnvironmentMap = async (
|
|
1602
1562
|
manifestArg: IResolvedSecretManifest,
|
|
1603
|
-
): Promise<
|
|
1563
|
+
): Promise<IWorkloadInitEnvironmentMap> => {
|
|
1604
1564
|
if (validateResolvedSecretManifest(manifestArg).length > 0
|
|
1605
1565
|
|| !await verifyResolvedSecretManifestDigest(manifestArg)) {
|
|
1606
1566
|
throw new Error('workload init map requires a valid digest-verified manifest');
|
|
@@ -1629,7 +1589,6 @@ export const createWorkloadInitEnvironmentMap = async (
|
|
|
1629
1589
|
throw new Error('workload init map entries must have unique variable, resource, and source fields');
|
|
1630
1590
|
}
|
|
1631
1591
|
return {
|
|
1632
|
-
schemaVersion: 1,
|
|
1633
1592
|
manifestId: manifestArg.id,
|
|
1634
1593
|
manifestDigest: manifestArg.digest,
|
|
1635
1594
|
entries,
|
|
@@ -1641,7 +1600,7 @@ export const verifyWorkloadInitEnvironmentMap = async (
|
|
|
1641
1600
|
manifestArg: IResolvedSecretManifest,
|
|
1642
1601
|
): Promise<boolean> => {
|
|
1643
1602
|
if (!isRecord(mapArg)
|
|
1644
|
-
|| !hasExactKeys(mapArg, ['
|
|
1603
|
+
|| !hasExactKeys(mapArg, ['manifestId', 'manifestDigest', 'entries'])) {
|
|
1645
1604
|
return false;
|
|
1646
1605
|
}
|
|
1647
1606
|
try {
|
|
@@ -1688,7 +1647,6 @@ export interface ISecretRuntimeResourceRetention {
|
|
|
1688
1647
|
export type TSecretRecipientLifecycleState = 'active' | 'retiring' | 'revoked';
|
|
1689
1648
|
|
|
1690
1649
|
interface ISecretRecipientMetadataBase {
|
|
1691
|
-
schemaVersion: 1;
|
|
1692
1650
|
recipientKeyId: string;
|
|
1693
1651
|
/** Canonical unpadded base64url raw 32-byte X25519 public key. */
|
|
1694
1652
|
publicKey: string;
|
|
@@ -1731,17 +1689,16 @@ export const validateSecretRecipientMetadata = (
|
|
|
1731
1689
|
if (!isRecord(recipientArg)) return ['secret recipient must be an object'];
|
|
1732
1690
|
const lifecycleState = recipientArg.lifecycleState;
|
|
1733
1691
|
const requiredKeys = lifecycleState === 'active'
|
|
1734
|
-
? ['
|
|
1692
|
+
? ['recipientKeyId', 'publicKey', 'generation', 'activatedAt', 'lifecycleState']
|
|
1735
1693
|
: lifecycleState === 'retiring'
|
|
1736
|
-
? ['
|
|
1694
|
+
? ['recipientKeyId', 'publicKey', 'generation', 'activatedAt', 'lifecycleState', 'acceptUntil']
|
|
1737
1695
|
: lifecycleState === 'revoked'
|
|
1738
|
-
? ['
|
|
1696
|
+
? ['recipientKeyId', 'publicKey', 'generation', 'activatedAt', 'lifecycleState', 'revokedAt']
|
|
1739
1697
|
: [];
|
|
1740
1698
|
if (requiredKeys.length === 0 || !hasExactKeys(recipientArg, requiredKeys)) {
|
|
1741
1699
|
return ['secret recipient must use its exact lifecycle schema'];
|
|
1742
1700
|
}
|
|
1743
1701
|
const errors: string[] = [];
|
|
1744
|
-
if (recipientArg.schemaVersion !== 1) errors.push('secret recipient schemaVersion must be 1');
|
|
1745
1702
|
if (!isSecretIdentifier(recipientArg.recipientKeyId)) {
|
|
1746
1703
|
errors.push('secret recipient key id must be canonical');
|
|
1747
1704
|
}
|
|
@@ -1877,7 +1834,6 @@ export const createSecretCreateEnvelopeContext = (contextArg: {
|
|
|
1877
1834
|
delivery: TSecretDelivery;
|
|
1878
1835
|
expectedTargetSecretsRevision: number;
|
|
1879
1836
|
}): Uint8Array => contextBytes({
|
|
1880
|
-
schemaVersion: 1,
|
|
1881
1837
|
purpose: 'serve.zone/secret-create',
|
|
1882
1838
|
mutationId: contextArg.mutationId,
|
|
1883
1839
|
target: canonicalSecretOwner(contextArg.target),
|
|
@@ -1894,7 +1850,6 @@ export const createSecretRotateEnvelopeContext = (contextArg: {
|
|
|
1894
1850
|
expectedActiveVersionId: string;
|
|
1895
1851
|
expectedTargetSecretsRevision: number;
|
|
1896
1852
|
}): Uint8Array => contextBytes({
|
|
1897
|
-
schemaVersion: 1,
|
|
1898
1853
|
purpose: 'serve.zone/secret-rotate',
|
|
1899
1854
|
mutationId: contextArg.mutationId,
|
|
1900
1855
|
secretId: contextArg.secretId,
|
|
@@ -1912,7 +1867,6 @@ export const createAppStoreInstallSecretEnvelopeContext = (contextArg: {
|
|
|
1912
1867
|
delivery: TSecretDelivery;
|
|
1913
1868
|
generation?: { encoding: TSecretGeneratedEncoding; bytes: number };
|
|
1914
1869
|
}): Uint8Array => contextBytes({
|
|
1915
|
-
schemaVersion: 1,
|
|
1916
1870
|
purpose: 'serve.zone/app-install-secret',
|
|
1917
1871
|
mutationId: contextArg.mutationId,
|
|
1918
1872
|
appId: contextArg.appId,
|
|
@@ -1940,7 +1894,6 @@ export const createResolvedSecretMaterialEnvelopeContext = (contextArg: {
|
|
|
1940
1894
|
secretId: string;
|
|
1941
1895
|
secretVersionId: string;
|
|
1942
1896
|
}): Uint8Array => contextBytes({
|
|
1943
|
-
schemaVersion: 1,
|
|
1944
1897
|
purpose: 'serve.zone/resolved-secret-material',
|
|
1945
1898
|
recipientKeyId: contextArg.recipientKeyId,
|
|
1946
1899
|
organizationId: contextArg.organizationId,
|
|
@@ -1965,7 +1918,6 @@ export const createSecretRecipientEnrollmentChallengeContext = (contextArg: {
|
|
|
1965
1918
|
generation: number;
|
|
1966
1919
|
expiresAt: number;
|
|
1967
1920
|
}): Uint8Array => contextBytes({
|
|
1968
|
-
schemaVersion: 1,
|
|
1969
1921
|
purpose: 'serve.zone/secret-recipient-enrollment-challenge',
|
|
1970
1922
|
enrollmentId: contextArg.enrollmentId,
|
|
1971
1923
|
clusterId: contextArg.clusterId,
|
|
@@ -1,19 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readDataElements, readDataProperty, readExactDataRecord,
|
|
3
|
+
} from '../private/dataproperties.js';
|
|
4
|
+
|
|
1
5
|
/** Workload permissions are independent of human membership and deployment grants. */
|
|
2
|
-
export type
|
|
6
|
+
export type TServiceMachineCapability = 'platform:session';
|
|
3
7
|
|
|
4
8
|
/** Exact existing-service authority. Never infer this grant from an API role. */
|
|
5
|
-
export interface
|
|
9
|
+
export interface IServiceMachineGrant {
|
|
6
10
|
organizationId: string;
|
|
7
11
|
serviceId: string;
|
|
8
|
-
capabilities:
|
|
12
|
+
capabilities: TServiceMachineCapability[];
|
|
9
13
|
}
|
|
10
14
|
|
|
11
15
|
/** Public metadata only. The bearer is delivered through the owning service's SecretSet. */
|
|
12
|
-
export interface
|
|
13
|
-
schemaVersion: 1;
|
|
16
|
+
export interface IServiceMachineCredentialMetadata {
|
|
14
17
|
credentialId: string;
|
|
15
18
|
userId: string;
|
|
16
|
-
grant:
|
|
19
|
+
grant: IServiceMachineGrant;
|
|
17
20
|
generation: number;
|
|
18
21
|
state: 'active' | 'revoked';
|
|
19
22
|
expiresAt: number;
|
|
@@ -23,8 +26,7 @@ export interface IServiceMachineCredentialMetadataV1 {
|
|
|
23
26
|
delivery: { secretId: string; secretVersionId: string } | null;
|
|
24
27
|
}
|
|
25
28
|
|
|
26
|
-
interface
|
|
27
|
-
schemaVersion: 1;
|
|
29
|
+
interface IServiceMachineCredentialMutationBase {
|
|
28
30
|
organizationId: string;
|
|
29
31
|
serviceId: string;
|
|
30
32
|
/** Retain the complete request and this ID across retries. */
|
|
@@ -32,41 +34,34 @@ interface IServiceMachineCredentialMutationBaseV1 {
|
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
/** Creation is absent-only; rotation and revocation require the exact current generation. */
|
|
35
|
-
export type
|
|
37
|
+
export type TServiceMachineCredentialMutation = IServiceMachineCredentialMutationBase & (
|
|
36
38
|
| {
|
|
37
39
|
operation: 'ensure';
|
|
38
40
|
expectedGeneration: null;
|
|
39
|
-
capabilities:
|
|
41
|
+
capabilities: TServiceMachineCapability[];
|
|
40
42
|
expiresAt: number;
|
|
41
43
|
}
|
|
42
44
|
| {
|
|
43
45
|
operation: 'rotate';
|
|
44
46
|
expectedGeneration: number;
|
|
45
|
-
capabilities:
|
|
47
|
+
capabilities: TServiceMachineCapability[];
|
|
46
48
|
expiresAt: number;
|
|
47
49
|
}
|
|
48
50
|
| { operation: 'revoke'; expectedGeneration: number }
|
|
49
51
|
);
|
|
50
52
|
|
|
51
|
-
export interface
|
|
53
|
+
export interface IServiceMachineCredentialMutationResult {
|
|
52
54
|
/** Historical on replay; replay never restores revoked or superseded authority. */
|
|
53
|
-
credential:
|
|
55
|
+
credential: IServiceMachineCredentialMetadata;
|
|
54
56
|
replayed: boolean;
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
const fail = (): never => { throw new Error('Service credential contract rejected.'); };
|
|
58
60
|
function requireValue(value: unknown): asserts value { if (!value) fail(); }
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
requireValue(actual.length === keys.length && keys.every((key) => actual.includes(key)));
|
|
64
|
-
const copy: Record<string, unknown> = Object.create(null);
|
|
65
|
-
for (const key of keys) {
|
|
66
|
-
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
67
|
-
requireValue(descriptor && Object.hasOwn(descriptor, 'value') && descriptor.enumerable);
|
|
68
|
-
copy[key] = descriptor.value;
|
|
69
|
-
}
|
|
61
|
+
/** Exactly this shape's keys, read once as data; an accessor is refused, never invoked. */
|
|
62
|
+
const object = (value: unknown, keys: readonly string[]): Record<string, unknown> => {
|
|
63
|
+
const copy = readExactDataRecord(value, keys);
|
|
64
|
+
requireValue(copy !== null);
|
|
70
65
|
return copy;
|
|
71
66
|
};
|
|
72
67
|
const identifier = (value: unknown): string => {
|
|
@@ -77,31 +72,26 @@ const counter = (value: unknown): number => {
|
|
|
77
72
|
requireValue(typeof value === 'number' && Number.isSafeInteger(value) && value > 0 && value < Number.MAX_SAFE_INTEGER);
|
|
78
73
|
return value;
|
|
79
74
|
};
|
|
80
|
-
const capabilities = (value: unknown):
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
requireValue(keys.length === 2 && keys.includes('length') && keys.includes('0'));
|
|
84
|
-
const entry = Object.getOwnPropertyDescriptor(value, '0');
|
|
85
|
-
requireValue(entry && Object.hasOwn(entry, 'value') && entry.enumerable && entry.value === 'platform:session');
|
|
75
|
+
const capabilities = (value: unknown): TServiceMachineCapability[] => {
|
|
76
|
+
const entries = readDataElements(value, 1);
|
|
77
|
+
requireValue(entries !== null && entries.length === 1 && entries[0] === 'platform:session');
|
|
86
78
|
return ['platform:session'];
|
|
87
79
|
};
|
|
88
80
|
const safe = <T>(operation: () => T): T => { try { return operation(); } catch { return fail(); } };
|
|
89
81
|
|
|
90
82
|
/** Structural copy only; the backend must fence live service ownership and credential authority. */
|
|
91
|
-
export const
|
|
83
|
+
export const snapshotServiceMachineGrant = (value: unknown): IServiceMachineGrant => safe(() => {
|
|
92
84
|
const grant = object(value, ['organizationId', 'serviceId', 'capabilities']);
|
|
93
85
|
return { organizationId: identifier(grant.organizationId), serviceId: identifier(grant.serviceId),
|
|
94
86
|
capabilities: capabilities(grant.capabilities) };
|
|
95
87
|
});
|
|
96
88
|
|
|
97
|
-
export const
|
|
98
|
-
|
|
99
|
-
const operation = Object.getOwnPropertyDescriptor(value, 'operation')?.value;
|
|
89
|
+
export const snapshotServiceMachineCredentialMutation = (value: unknown): TServiceMachineCredentialMutation => safe(() => {
|
|
90
|
+
const operation = readDataProperty(value, 'operation')?.value;
|
|
100
91
|
requireValue(operation === 'ensure' || operation === 'rotate' || operation === 'revoke');
|
|
101
|
-
const request = object(value, ['
|
|
92
|
+
const request = object(value, ['organizationId', 'serviceId', 'mutationId', 'operation',
|
|
102
93
|
'expectedGeneration', ...(operation === 'revoke' ? [] : ['capabilities', 'expiresAt'])]);
|
|
103
|
-
|
|
104
|
-
const base = { schemaVersion: 1 as const, organizationId: identifier(request.organizationId),
|
|
94
|
+
const base = { organizationId: identifier(request.organizationId),
|
|
105
95
|
serviceId: identifier(request.serviceId), mutationId: identifier(request.mutationId) };
|
|
106
96
|
if (operation === 'revoke') return { ...base, operation, expectedGeneration: counter(request.expectedGeneration) };
|
|
107
97
|
const material = { capabilities: capabilities(request.capabilities), expiresAt: counter(request.expiresAt) };
|
|
@@ -112,19 +102,19 @@ export const snapshotServiceMachineCredentialMutationV1 = (value: unknown): TSer
|
|
|
112
102
|
return { ...base, ...material, operation, expectedGeneration: counter(request.expectedGeneration) };
|
|
113
103
|
});
|
|
114
104
|
|
|
115
|
-
export const
|
|
116
|
-
const metadata = object(value, ['
|
|
105
|
+
export const snapshotServiceMachineCredentialMetadata = (value: unknown): IServiceMachineCredentialMetadata => safe(() => {
|
|
106
|
+
const metadata = object(value, ['credentialId', 'userId', 'grant', 'generation', 'state',
|
|
117
107
|
'expiresAt', 'createdAt', 'updatedAt', 'delivery']);
|
|
118
|
-
requireValue(metadata.
|
|
108
|
+
requireValue(metadata.state === 'active' || metadata.state === 'revoked');
|
|
119
109
|
const createdAt = counter(metadata.createdAt);
|
|
120
110
|
const updatedAt = counter(metadata.updatedAt);
|
|
121
111
|
requireValue(updatedAt >= createdAt);
|
|
122
|
-
let delivery:
|
|
112
|
+
let delivery: IServiceMachineCredentialMetadata['delivery'] = null;
|
|
123
113
|
if (metadata.state === 'active') {
|
|
124
114
|
const version = object(metadata.delivery, ['secretId', 'secretVersionId']);
|
|
125
115
|
delivery = { secretId: identifier(version.secretId), secretVersionId: identifier(version.secretVersionId) };
|
|
126
116
|
} else requireValue(metadata.delivery === null);
|
|
127
|
-
return {
|
|
128
|
-
grant:
|
|
117
|
+
return { credentialId: identifier(metadata.credentialId), userId: identifier(metadata.userId),
|
|
118
|
+
grant: snapshotServiceMachineGrant(metadata.grant), generation: counter(metadata.generation),
|
|
129
119
|
state: metadata.state, expiresAt: counter(metadata.expiresAt), createdAt, updatedAt, delivery };
|
|
130
120
|
});
|