@serve.zone/interfaces 32.58.0 → 32.60.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,89 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026-10-20 - 32.60.0
4
+
5
+ ### Fixes
6
+
7
+ - External registry reads stop carrying the credential the server must never send. Every
8
+ `requests.externalRegistry` response (`getExternalRegistryById`, `getExternalRegistries`,
9
+ `createExternalRegistry`, `updateExternalRegistry`, `verifyExternalRegistry`) now answers
10
+ `data.IExternalRegistryPublic`: the registry without `data.password` and with a required
11
+ `passwordConfigured`. `IExternalRegistry` stays the stored shape, and its `data.password` is
12
+ documented as write-only.
13
+ - `IReq_UpdateRegistry.request.registryData` is a `Partial` of the operator fields
14
+ (`TExternalRegistryOperatorData`, names in `TExternalRegistryOperatorField`): status, last error
15
+ and timestamps belong to Cloudly and can no longer be sent. A missing or empty `password` keeps
16
+ the stored one; `authType: 'none'` removes it.
17
+ - `IReq_VerifyRegistry.response` carries a required `outcome` (`TExternalRegistryVerifyOutcome`:
18
+ `authenticated`, `anonymous`, `credentials-not-exercised`, `authentication-failed`,
19
+ `unreachable`, `unsupported`) and a required `registry`, so a registry that answers anonymously
20
+ no longer reads as verified credentials.
21
+
22
+ ### Features
23
+
24
+ - `composeObjectStorageServiceEnvironment(serviceEnvironment, sources, secretEnvironmentNames?)`:
25
+ the names, without values, of the variables the workload receives as launcher-environment
26
+ secrets. The launcher sets a secret over a plain variable of the same name, so a secret named
27
+ like one of a binding's names (`objectStorageBindingEnvironmentKeys`, such as `S3_ENDPOINT`)
28
+ would silently replace the binding's value; it is refused as
29
+ `objectstorage-environment-conflict`, exactly as the same name in the service's own environment
30
+ is, and the message names it as a secret. Other secret names, including the binding's own
31
+ credentials (`corestoreObjectStorageCredentialSecretKeys`), are not conflicts. Omitted, the
32
+ composition treats the workload as receiving none; the input becomes required in the coordinated
33
+ major.
34
+ - `IRequest_Any_Cloudly_UpdateService.request.serviceData` is a
35
+ `Partial<TServiceUpdateWritableData>`, matching the merge Cloudly performs: an omitted key keeps
36
+ its stored value, a stated key replaces it whole, and `containerArgs: null` removes the stored
37
+ argument vector. A client sends only the fields it changes, so an edit no longer has to restate
38
+ `placement` or `scaleFactor`, which a service with a runtime spec (and an immutable service)
39
+ refuses whenever an update states them. The full shape still type-checks, so existing callers
40
+ compile unchanged.
41
+ - `deriveLauncherSecretDeliveryOwner({ runAs, imageUsers, launcherDeliveries })` (`data`): the one
42
+ rule for the owner of a workload's launcher-environment secret files, which WorkloadInit reads as
43
+ the workload's own process identity. A `runAs` pair wins; under `runAs: null` an image without a
44
+ user is `0:0`, a numeric `user:group` is taken as stated, `root` stands for `0`, and a numeric
45
+ user without a group or with a named group is `user:0` while every launcher delivery is `0o400`.
46
+ `imageUsers` is Cloudly's canonical image user (`parseCanonicalImageUser`), one per platform of
47
+ the pinned digest; group readability is computed from `launcherDeliveries`. A named user, a
48
+ numeric part above the identity bound, a `0o440` delivery whose group the image does not state
49
+ numerically (the refusal names it in `variableName`), or platforms that derive different owners
50
+ refuse as the new service runtime refusal `launcher-secret-ownership-unknown`
51
+ (`TLauncherSecretDeliveryOwner`, with a `message`); a workload without launcher deliveries is
52
+ `not-required`. An image running as a non-root user is no longer handed secret files it cannot
53
+ read. Only a structurally malformed input throws.
54
+ - A resolved secret manifest's deliveries are their own type, `TSecretResolvedDelivery`, whose
55
+ launcher member `ISecretResolvedLauncherEnvironmentDelivery` requires `uid` and `gid`: the owner
56
+ the resolver derived, under the same keys, so the manifest's wire format and digest do not change
57
+ and every node keeps mounting it. `IResolvedSecretManifestEntry.delivery` is that type,
58
+ `validateSecretResolvedDelivery` checks it (`validateResolvedSecretManifest` uses it), and
59
+ `createResolvedSecretDelivery(delivery, owner)` builds it from a caller's delivery and the derived
60
+ owner.
61
+
62
+ ### Deprecations
63
+
64
+ - `ISecretLauncherEnvironmentDelivery`, the launcher delivery a caller states (a Secret's
65
+ `defaultDelivery`, a SecretSet attachment override, a create request, an App Store declaration),
66
+ makes `uid` and `gid` optional and deprecated: the resolver ignores them and writes the derived
67
+ owner into the resolved delivery. `validateSecretDelivery` prefers neither and tolerates both
68
+ (bounded) until the next major, which removes them; a sealed context that states them still
69
+ verifies. File deliveries keep their stated owner.
70
+
71
+ ### Maintenance
72
+
73
+ - Release tooling: pnpm 12.13.0; the other build and test tooling is current.
74
+
75
+ ## 2026-10-18 - 32.59.0
76
+
77
+ ### Features
78
+
79
+ - `IDomain.data.gatewayListedAt` (optional timestamp): when the dcrouter gateway last listed the
80
+ domain to this Cloudly; absent while the gateway does not list it. The gateway sync owns it,
81
+ separately from the operator's `activationState`.
82
+
83
+ ### Maintenance
84
+
85
+ - release tooling: pnpm 12.12.1
86
+
3
87
  ## 2026-10-17 - 32.58.0
4
88
 
5
89
  ### Features
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '32.58.0',
6
+ version: '32.60.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFNBQVM7SUFDbEIsV0FBVyxFQUFFLHVGQUF1RjtDQUNyRyxDQUFBIn0=
@@ -86,6 +86,12 @@ export interface IDomain {
86
86
  */
87
87
  syncSource?: 'cloudflare' | 'manual' | null;
88
88
  lastSyncAt?: number;
89
+ /**
90
+ * When the dcrouter gateway last listed this domain to this Cloudly (timestamp).
91
+ * Absent while the gateway does not list the domain. The gateway sync owns this
92
+ * member; it is independent of the operator's `activationState`.
93
+ */
94
+ gatewayListedAt?: number;
89
95
  /**
90
96
  * Whether domain is managed externally
91
97
  */
@@ -1,3 +1,7 @@
1
+ /**
2
+ * An external registry as Cloudly stores it, credential included. Never answered: every external
3
+ * registry response carries `IExternalRegistryPublic`.
4
+ */
1
5
  export interface IExternalRegistry {
2
6
  id: string;
3
7
  data: {
@@ -18,7 +22,10 @@ export interface IExternalRegistry {
18
22
  */
19
23
  username?: string;
20
24
  /**
21
- * Password, access token, or API key for authentication (optional for public registries)
25
+ * Password, access token or API key for authentication (optional for public registries).
26
+ *
27
+ * Write-only: Cloudly stores it and uses it server-side, and never answers it. Reads carry
28
+ * `IExternalRegistryPublic.passwordConfigured` instead.
22
29
  */
23
30
  password?: string;
24
31
  /**
@@ -90,3 +97,32 @@ export interface IExternalRegistry {
90
97
  updatedAt?: number;
91
98
  };
92
99
  }
100
+ /**
101
+ * An external registry as Cloudly answers it: the stored registry without its credential, and
102
+ * whether one is stored.
103
+ */
104
+ export interface IExternalRegistryPublic {
105
+ id: string;
106
+ data: Omit<IExternalRegistry['data'], 'password'>;
107
+ /** Whether a password, access token or API key is stored for the registry. */
108
+ passwordConfigured: boolean;
109
+ }
110
+ /** The registry fields an operator writes; Cloudly owns status, errors and timestamps. */
111
+ export type TExternalRegistryOperatorField = 'type' | 'name' | 'url' | 'username' | 'password' | 'description' | 'isDefault' | 'authType' | 'insecure' | 'namespace' | 'proxy' | 'config';
112
+ export type TExternalRegistryOperatorData = Pick<IExternalRegistry['data'], TExternalRegistryOperatorField>;
113
+ /**
114
+ * What a registry verification proved.
115
+ *
116
+ * - `authenticated`: the registry admitted the stored credentials (Basic, or a token its Bearer
117
+ * realm issued for them).
118
+ * - `anonymous`: the registry answers without authentication and none is configured.
119
+ * - `credentials-not-exercised`: credentials are configured, but the registry answers without
120
+ * authentication, so they were never checked.
121
+ * - `authentication-failed`: the registry, or its token realm, refused the credentials, or it
122
+ * requires authentication and none is configured.
123
+ * - `unreachable`: no usable answer (connection, TLS, timeout or an unexpected HTTP status).
124
+ * - `unsupported`: the registry or its configuration cannot be verified (an npm registry, OAuth2,
125
+ * an unknown or missing authentication challenge, a redirect, or credentials over plain HTTP
126
+ * without `insecure`).
127
+ */
128
+ export type TExternalRegistryVerifyOutcome = 'authenticated' | 'anonymous' | 'credentials-not-exercised' | 'authentication-failed' | 'unreachable' | 'unsupported';
@@ -81,6 +81,7 @@ export * from './servicecredential.js';
81
81
  export * from './serviceplatformownership.js';
82
82
  export * from './serviceports.js';
83
83
  export * from './serviceruntime.js';
84
+ export * from './launchersecretowner.js';
84
85
  export * from './servicevolumeinitialization.js';
85
86
  export * from './status.js';
86
87
  export * from './taskexecution.js';
@@ -77,6 +77,7 @@ export * from './servicecredential.js';
77
77
  export * from './serviceplatformownership.js';
78
78
  export * from './serviceports.js';
79
79
  export * from './serviceruntime.js';
80
+ export * from './launchersecretowner.js';
80
81
  export * from './servicevolumeinitialization.js';
81
82
  export * from './status.js';
82
83
  export * from './taskexecution.js';
@@ -84,4 +85,4 @@ export * from './traffic.js';
84
85
  export * from './user.js';
85
86
  export * from './version.js';
86
87
  export * from './webpush.js';
87
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxnQ0FBZ0MsQ0FBQztBQUMvQyxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLDhCQUE4QixDQUFDO0FBQzdDLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMsdUJBQXVCLENBQUM7QUFDdEMsY0FBYyxpQkFBaUIsQ0FBQztBQUNoQyxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMsNkJBQTZCLENBQUM7QUFDNUMsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLFVBQVUsQ0FBQztBQUN6QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsc0JBQXNCLENBQUM7QUFDckMsY0FBYyw2QkFBNkIsQ0FBQztBQUM1QyxjQUFjLFdBQVcsQ0FBQztBQUMxQixjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMseUJBQXlCLENBQUM7QUFDeEMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLDhCQUE4QixDQUFDO0FBQzdDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLHdCQUF3QixDQUFDO0FBR3ZDLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRzlELE9BQU8sRUFBRSxxQ0FBcUMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRXBGLE9BQU8sRUFBRSwwQ0FBMEMsRUFBRSwwQ0FBMEMsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQzFJLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLDRCQUE0QixDQUFDO0FBQzNDLGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYyw2QkFBNkIsQ0FBQztBQUM1QyxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYywrQkFBK0IsQ0FBQztBQUM5QyxjQUFjLGdDQUFnQyxDQUFDO0FBQy9DLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyxtQkFBbUIsQ0FBQztBQUNsQyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsa0NBQWtDLENBQUM7QUFDakQsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxvQkFBb0IsQ0FBQztBQUNuQyxjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLFdBQVcsQ0FBQztBQUMxQixjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLGNBQWMsQ0FBQyJ9
88
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyxnQ0FBZ0MsQ0FBQztBQUMvQyxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLDhCQUE4QixDQUFDO0FBQzdDLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMsdUJBQXVCLENBQUM7QUFDdEMsY0FBYyxpQkFBaUIsQ0FBQztBQUNoQyxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMsNkJBQTZCLENBQUM7QUFDNUMsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLFVBQVUsQ0FBQztBQUN6QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsc0JBQXNCLENBQUM7QUFDckMsY0FBYyw2QkFBNkIsQ0FBQztBQUM1QyxjQUFjLFdBQVcsQ0FBQztBQUMxQixjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMseUJBQXlCLENBQUM7QUFDeEMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLDhCQUE4QixDQUFDO0FBQzdDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLHdCQUF3QixDQUFDO0FBR3ZDLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRzlELE9BQU8sRUFBRSxxQ0FBcUMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRXBGLE9BQU8sRUFBRSwwQ0FBMEMsRUFBRSwwQ0FBMEMsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQzFJLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLDRCQUE0QixDQUFDO0FBQzNDLGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYyw2QkFBNkIsQ0FBQztBQUM1QyxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYywrQkFBK0IsQ0FBQztBQUM5QyxjQUFjLGdDQUFnQyxDQUFDO0FBQy9DLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyxtQkFBbUIsQ0FBQztBQUNsQyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyxrQ0FBa0MsQ0FBQztBQUNqRCxjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsV0FBVyxDQUFDO0FBQzFCLGNBQWMsY0FBYyxDQUFDO0FBQzdCLGNBQWMsY0FBYyxDQUFDIn0=
@@ -0,0 +1,60 @@
1
+ import type { ISecretLauncherEnvironmentDelivery } from './secret.js';
2
+ import type { IServiceRuntimeProfile, TServiceRuntimeRefusal } from './serviceruntime.js';
3
+ /** What the owner of a workload's launcher-environment secret files derives from. */
4
+ export interface ILauncherSecretDeliveryOwnerInput {
5
+ /** The runtime spec's `profile.runAs`; null runs the image's own OCI user. */
6
+ runAs: IServiceRuntimeProfile['runAs'];
7
+ /**
8
+ * The unresolved OCI `config.User` of the pinned digest's image config in Cloudly's canonical
9
+ * form (what its registry manager's `parseCanonicalImageUser` answers, never the raw registry
10
+ * value): `user` or `user:group`, each part a numeric identity or a name, and null for an image
11
+ * that states none or an empty `User`. One entry for a single-platform manifest, one per
12
+ * platform of a multi-platform index; never empty.
13
+ */
14
+ imageUsers: (string | null)[];
15
+ /**
16
+ * Every launcher-environment delivery the workload receives, as its caller states it. A `0o440`
17
+ * delivery grants the derived group, so that group has to be one the image states numerically.
18
+ */
19
+ launcherDeliveries: Pick<ISecretLauncherEnvironmentDelivery, 'variableName' | 'mode'>[];
20
+ }
21
+ /**
22
+ * The numeric owner of a workload's launcher-environment secret files, or why it derives none.
23
+ *
24
+ * `not-required` is a workload without launcher-environment deliveries: no file needs an owner, so
25
+ * nothing about the image refuses it.
26
+ *
27
+ * `launcher-secret-ownership-unknown` is a runtime spec that runs the image's own user
28
+ * (`runAs: null`) while that user's numeric owner is not known: a named user other than `root`, a
29
+ * numeric part above the runtime identity bound, a group-readable (`0o440`) delivery whose group
30
+ * the image does not state numerically, or platforms of a multi-platform index that derive
31
+ * different owners. `variableName` names the group-readable delivery that caused it (the first by
32
+ * name), null for the others; `message` states the cause.
33
+ */
34
+ export type TLauncherSecretDeliveryOwner = {
35
+ status: 'derived';
36
+ uid: number;
37
+ gid: number;
38
+ } | {
39
+ status: 'not-required';
40
+ } | {
41
+ status: 'refused';
42
+ reason: Extract<TServiceRuntimeRefusal, 'launcher-secret-ownership-unknown'>;
43
+ variableName: string | null;
44
+ message: string;
45
+ };
46
+ /**
47
+ * The owner Cloudly gives every launcher-environment secret file of a workload, which WorkloadInit
48
+ * reads as the workload's own process identity before it starts the image.
49
+ *
50
+ * Without launcher deliveries it is `not-required`. A `runAs` pair wins over the image. Under
51
+ * `runAs: null` an image without a user runs as root (`0:0`, the runtime config's own default), a
52
+ * numeric `user:group` is taken as stated and `root` stands for `0` in either part. A numeric user
53
+ * without a group, or with a named group, is `user:0` while every delivery is owner-readable
54
+ * (`0o400`), which grants the group nothing; a `0o440` delivery would grant it, so it refuses and
55
+ * names that delivery. A named user, or a numeric part above the runtime identity bound, refuses.
56
+ * Every platform of a multi-platform index must derive
57
+ * the same owner, or it refuses: a workload gets one delivery, never one per platform. Nothing is
58
+ * guessed. A structurally malformed input throws, whatever it would answer.
59
+ */
60
+ export declare const deriveLauncherSecretDeliveryOwner: (inputArg: ILauncherSecretDeliveryOwnerInput) => TLauncherSecretDeliveryOwner;
@@ -0,0 +1,94 @@
1
+ import { hasExactKeys, isPlainRecord } from '../private/dataproperties.js';
2
+ import { isRuntimeIdentityNumber, runtimePolicyLimits } from '../private/runtimepolicy.js';
3
+ const imageUserPartPattern = /^[^:\u0000-\u001f\u007f]+$/;
4
+ const imageUserPart = (partArg) => {
5
+ if (partArg === 'root')
6
+ return 0;
7
+ if (!/^[0-9]+$/.test(partArg))
8
+ return 'named';
9
+ const identity = Number(partArg);
10
+ return isRuntimeIdentityNumber(identity) ? identity : 'unbounded';
11
+ };
12
+ /** One platform's user and group; an absent group is `undefined`. A malformed image user throws. */
13
+ const imageUserParts = (imageUserArg) => {
14
+ if (imageUserArg === null)
15
+ return { user: 0, group: 0 };
16
+ const parts = typeof imageUserArg === 'string' ? imageUserArg.split(':') : [];
17
+ if (parts.length === 0 || parts.length > 2 || !parts.every((partArg) => imageUserPartPattern.test(partArg))) {
18
+ throw new Error('image user must be null, user or user:group');
19
+ }
20
+ return { user: imageUserPart(parts[0]), group: parts[1] === undefined ? undefined : imageUserPart(parts[1]) };
21
+ };
22
+ /** The names of the group-readable (`0o440`) deliveries, sorted; a malformed delivery throws. */
23
+ const groupReadableVariableNames = (deliveriesArg) => {
24
+ if (!Array.isArray(deliveriesArg))
25
+ throw new Error('launcherDeliveries must list the launcher deliveries');
26
+ const names = [];
27
+ for (const delivery of deliveriesArg) {
28
+ if (!isPlainRecord(delivery) || typeof delivery.variableName !== 'string' || delivery.variableName === ''
29
+ || (delivery.mode !== 0o400 && delivery.mode !== 0o440)) {
30
+ throw new Error('a launcher delivery must state its variableName and a 0400 or 0440 mode');
31
+ }
32
+ if (delivery.mode === 0o440)
33
+ names.push(delivery.variableName);
34
+ }
35
+ return names.sort();
36
+ };
37
+ const refusal = (variableNameArg, messageArg) => ({
38
+ status: 'refused', reason: 'launcher-secret-ownership-unknown', variableName: variableNameArg, message: messageArg,
39
+ });
40
+ /**
41
+ * The owner Cloudly gives every launcher-environment secret file of a workload, which WorkloadInit
42
+ * reads as the workload's own process identity before it starts the image.
43
+ *
44
+ * Without launcher deliveries it is `not-required`. A `runAs` pair wins over the image. Under
45
+ * `runAs: null` an image without a user runs as root (`0:0`, the runtime config's own default), a
46
+ * numeric `user:group` is taken as stated and `root` stands for `0` in either part. A numeric user
47
+ * without a group, or with a named group, is `user:0` while every delivery is owner-readable
48
+ * (`0o400`), which grants the group nothing; a `0o440` delivery would grant it, so it refuses and
49
+ * names that delivery. A named user, or a numeric part above the runtime identity bound, refuses.
50
+ * Every platform of a multi-platform index must derive
51
+ * the same owner, or it refuses: a workload gets one delivery, never one per platform. Nothing is
52
+ * guessed. A structurally malformed input throws, whatever it would answer.
53
+ */
54
+ export const deriveLauncherSecretDeliveryOwner = (inputArg) => {
55
+ const { runAs, imageUsers, launcherDeliveries } = inputArg;
56
+ if (runAs !== null && !(isPlainRecord(runAs) && hasExactKeys(runAs, ['user', 'group'])
57
+ && isRuntimeIdentityNumber(runAs.user) && isRuntimeIdentityNumber(runAs.group))) {
58
+ throw new Error('runAs must be null or an exact user and group');
59
+ }
60
+ if (!Array.isArray(imageUsers) || imageUsers.length === 0) {
61
+ throw new Error('imageUsers must name the user of every platform');
62
+ }
63
+ const platforms = imageUsers.map(imageUserParts);
64
+ const groupReadable = groupReadableVariableNames(launcherDeliveries);
65
+ if (launcherDeliveries.length === 0)
66
+ return { status: 'not-required' };
67
+ if (runAs !== null)
68
+ return { status: 'derived', uid: runAs.user, gid: runAs.group };
69
+ const userOf = (predicateArg) => (imageUsers.find((_imageUserArg, indexArg) => predicateArg(platforms[indexArg])));
70
+ const unbounded = userOf((platformArg) => platformArg.user === 'unbounded' || platformArg.group === 'unbounded');
71
+ if (unbounded !== undefined) {
72
+ return refusal(null, `image user '${unbounded}' states an identity above `
73
+ + `${runtimePolicyLimits.maximumIdentityNumber}`);
74
+ }
75
+ const namedUser = userOf((platformArg) => platformArg.user === 'named');
76
+ if (namedUser !== undefined) {
77
+ return refusal(null, `image user '${namedUser}' names a user only the image's root filesystem resolves`);
78
+ }
79
+ const ungrouped = userOf((platformArg) => typeof platformArg.group !== 'number');
80
+ if (ungrouped !== undefined && groupReadable.length > 0) {
81
+ return refusal(groupReadable[0], `launcher-environment secret ${groupReadable.join(', ')} is group-readable `
82
+ + `(0440), but image user '${ungrouped}' states no numeric group`);
83
+ }
84
+ // Every part is now a bounded number, or a group that an owner-readable file does not grant.
85
+ const [first, ...rest] = platforms.map((platformArg) => ({
86
+ uid: platformArg.user, gid: typeof platformArg.group === 'number' ? platformArg.group : 0,
87
+ }));
88
+ if (rest.some((ownerArg) => ownerArg.uid !== first.uid || ownerArg.gid !== first.gid)) {
89
+ const users = imageUsers.map((userArg) => userArg === null ? 'none' : `'${userArg}'`).join(', ');
90
+ return refusal(null, `the platforms' image users ${users} derive different owners`);
91
+ }
92
+ return { status: 'derived', uid: first.uid, gid: first.gid };
93
+ };
94
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGF1bmNoZXJzZWNyZXRvd25lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2RhdGEvbGF1bmNoZXJzZWNyZXRvd25lci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsWUFBWSxFQUFFLGFBQWEsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzNFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBNEMzRixNQUFNLG9CQUFvQixHQUFHLDRCQUE0QixDQUFDO0FBUTFELE1BQU0sYUFBYSxHQUFHLENBQUMsT0FBZSxFQUFrQixFQUFFO0lBQ3hELElBQUksT0FBTyxLQUFLLE1BQU07UUFBRSxPQUFPLENBQUMsQ0FBQztJQUNqQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7UUFBRSxPQUFPLE9BQU8sQ0FBQztJQUM5QyxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDakMsT0FBTyx1QkFBdUIsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUM7QUFDcEUsQ0FBQyxDQUFDO0FBRUYsb0dBQW9HO0FBQ3BHLE1BQU0sY0FBYyxHQUFHLENBQUMsWUFBcUIsRUFBK0QsRUFBRTtJQUM1RyxJQUFJLFlBQVksS0FBSyxJQUFJO1FBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ3hELE1BQU0sS0FBSyxHQUFHLE9BQU8sWUFBWSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQzlFLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FB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
@@ -151,7 +151,32 @@ export interface ISecretSetConsumerRolloutStatus {
151
151
  errorCode?: string;
152
152
  updatedAt: number;
153
153
  }
154
+ /**
155
+ * A launcher-environment delivery as a caller states it: on a Secret's `defaultDelivery`, a
156
+ * SecretSet attachment override, a create request or an App Store declaration. The owner of the
157
+ * file WorkloadInit reads is not the caller's to state; the resolver derives it.
158
+ */
154
159
  export interface ISecretLauncherEnvironmentDelivery {
160
+ type: 'launcher-environment';
161
+ variableName: string;
162
+ /**
163
+ * @deprecated Derived by the resolver from the workload identity
164
+ * (`deriveLauncherSecretDeliveryOwner`); ignored; removed in the next major.
165
+ */
166
+ uid?: number;
167
+ /**
168
+ * @deprecated Derived by the resolver from the workload identity
169
+ * (`deriveLauncherSecretDeliveryOwner`); ignored; removed in the next major.
170
+ */
171
+ gid?: number;
172
+ mode: 0o400 | 0o440;
173
+ }
174
+ /**
175
+ * A launcher-environment delivery of a resolved secret manifest. `uid` and `gid` are the owner the
176
+ * resolver derived from the workload identity (`deriveLauncherSecretDeliveryOwner`), written by
177
+ * `createResolvedSecretDelivery`; the node mounts the file with them.
178
+ */
179
+ export interface ISecretResolvedLauncherEnvironmentDelivery {
155
180
  type: 'launcher-environment';
156
181
  variableName: string;
157
182
  uid: number;
@@ -165,7 +190,10 @@ export interface ISecretFileDelivery {
165
190
  gid: number;
166
191
  mode: 0o400 | 0o440;
167
192
  }
193
+ /** A delivery as a caller states it. */
168
194
  export type TSecretDelivery = ISecretLauncherEnvironmentDelivery | ISecretFileDelivery;
195
+ /** A delivery of a resolved secret manifest: every owner is stated. */
196
+ export type TSecretResolvedDelivery = ISecretResolvedLauncherEnvironmentDelivery | ISecretFileDelivery;
169
197
  export declare const secretValueLimits: Readonly<{
170
198
  maximumBytes: number;
171
199
  minimumGeneratedBytes: 16;
@@ -211,7 +239,7 @@ export interface IResolvedSecretManifestEntry {
211
239
  key: string;
212
240
  environment: TSecretEnvironment;
213
241
  owner: TWorkloadSecretOwner;
214
- delivery: TSecretDelivery;
242
+ delivery: TSecretResolvedDelivery;
215
243
  }
216
244
  /** Immutable, value-free runtime snapshot. */
217
245
  export interface IResolvedSecretManifest {
@@ -272,7 +300,22 @@ export declare const verifySecretVersionPurgeIntentDigest: (intentArg: ISecretVe
272
300
  export declare const validateSecretVersionPurgeOperation: (operationArg: unknown) => Promise<string[]>;
273
301
  export declare const validateSecretOwner: (ownerArg: unknown) => string[];
274
302
  export declare const validateSecretManagementScope: (sourceArg: TSecretManagementSource, scopeArg: unknown) => string[];
303
+ /**
304
+ * Validates a delivery as a caller states it. A launcher delivery should state no owner; one that
305
+ * states the deprecated `uid` and `gid` (both, bounded) is tolerated until the next major.
306
+ */
275
307
  export declare const validateSecretDelivery: (deliveryArg: unknown) => string[];
308
+ /** Validates a resolved manifest's delivery: a launcher delivery states its derived owner. */
309
+ export declare const validateSecretResolvedDelivery: (deliveryArg: unknown) => string[];
310
+ /**
311
+ * The resolved manifest delivery of a caller's delivery: a launcher delivery takes the owner the
312
+ * resolver derived (`deriveLauncherSecretDeliveryOwner`) and drops any deprecated owner the caller
313
+ * stated; a file delivery keeps its own.
314
+ */
315
+ export declare const createResolvedSecretDelivery: (deliveryArg: TSecretDelivery, ownerArg: {
316
+ uid: number;
317
+ gid: number;
318
+ }) => TSecretResolvedDelivery;
276
319
  export declare const validateSecretMetadata: (secretArg: unknown) => string[];
277
320
  export declare const validateSecretValueInput: (valueInputArg: unknown) => string[];
278
321
  /** Checks the SmartCrypto context digest without opening or decrypting the envelope. */