@serve.zone/interfaces 18.0.0 → 19.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +19 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/appstore/types.d.ts +24 -0
- package/dist_ts/appstore/types.js +76 -1
- package/dist_ts/data/hostedapp.d.ts +72 -0
- package/dist_ts/data/hostedapp.js +191 -2
- package/dist_ts/data/immutableimage.d.ts +2 -0
- package/dist_ts/data/immutableimage.js +1 -1
- package/dist_ts/requests/corestore.d.ts +37 -3
- package/package.json +1 -1
- package/readme.md +39 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/appstore/types.ts +109 -0
- package/ts/data/hostedapp.ts +268 -0
- package/ts/data/immutableimage.ts +2 -0
- package/ts/requests/corestore.ts +53 -3
package/changelog.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026-07-24 - 19.0.0
|
|
4
|
+
|
|
5
|
+
### Breaking Changes
|
|
6
|
+
|
|
7
|
+
- add versioned corestore inventory reports with per-node probes (corestore-inventory)
|
|
8
|
+
- Change getCorestoreInventory response to return an ICorestoreInventoryReport with inventories and per-node probes.
|
|
9
|
+
- Require protocolVersion and checkedAt on corestore node inventories and add structured error codes.
|
|
10
|
+
- Add coreflow capability and registration interfaces for versioned inventory probing.
|
|
11
|
+
|
|
12
|
+
## 2026-07-23 - 18.1.0
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
- add host-neutral platform OIDC and app-scoped role contracts for hosted apps
|
|
17
|
+
- Declare App Store OIDC capabilities without enabling them automatically.
|
|
18
|
+
- Bind client identity, token audience, and role assignments to an immutable app instance.
|
|
19
|
+
- Validate canonical same-origin callbacks, secret environment mappings, registrations, and audience-scoped claims.
|
|
20
|
+
- Document the shared per-instance enablement contract for Onebox and Cloudly.
|
|
21
|
+
|
|
3
22
|
## 2026-07-23 - 18.0.0
|
|
4
23
|
|
|
5
24
|
### Breaking Changes
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/interfaces',
|
|
6
|
-
version: '
|
|
6
|
+
version: '19.0.0',
|
|
7
7
|
description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLHVGQUF1RjtDQUNyRyxDQUFBIn0=
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { IServiceSecretFile } from '../data/service.js';
|
|
2
|
+
import { type IHostedAppRoleDefinition } from '../data/hostedapp.js';
|
|
2
3
|
import type { IServiceDomainRoute, IServicePublicPortMapping, IServiceTargetPort } from '../data/serviceports.js';
|
|
3
4
|
import type { IStorageCapacityRequest, IStorageClassRequirement, TFilesystemStorageAccessMode, TObjectStorageAccessMode, TObjectStorageDelivery, TStorageReclaimPolicy, TStorageResourceKind, TStorageSnapshotMode } from '../platform/storage.js';
|
|
4
5
|
export type TAppStorePlatformRequirement = 'mongodb' | 's3' | 'clickhouse' | 'valkey' | 'mariadb';
|
|
@@ -132,6 +133,23 @@ export interface IAppStorePublishedPort {
|
|
|
132
133
|
protocol?: 'tcp' | 'udp';
|
|
133
134
|
hostIp?: string;
|
|
134
135
|
}
|
|
136
|
+
export interface IAppStorePlatformOidcEnvironmentVariables {
|
|
137
|
+
issuerUrl: string;
|
|
138
|
+
clientId: string;
|
|
139
|
+
/** The hosting platform must deliver this value through its secret environment path. */
|
|
140
|
+
clientSecret: string;
|
|
141
|
+
redirectUri: string;
|
|
142
|
+
audience: string;
|
|
143
|
+
}
|
|
144
|
+
export interface IAppStorePlatformOidcCapability {
|
|
145
|
+
/** Callback path relative to the app's canonical HTTPS origin. */
|
|
146
|
+
redirectPath: string;
|
|
147
|
+
roles: IHostedAppRoleDefinition[];
|
|
148
|
+
environmentVariables: IAppStorePlatformOidcEnvironmentVariables;
|
|
149
|
+
clientAuthenticationMethod: 'client_secret_basic' | 'client_secret_post';
|
|
150
|
+
}
|
|
151
|
+
export declare const validateAppStorePlatformOidcCapability: (capabilityArg: unknown) => string[];
|
|
152
|
+
export declare const validateAppStoreVersionPlatformOidc: (configArg: unknown) => string[];
|
|
135
153
|
export interface IAppStoreApp {
|
|
136
154
|
id: string;
|
|
137
155
|
name: string;
|
|
@@ -197,6 +215,12 @@ export interface IAppStoreVersionConfig {
|
|
|
197
215
|
storageRequests?: TAppStoreStorageRequest[];
|
|
198
216
|
publishedPorts?: IAppStorePublishedPort[];
|
|
199
217
|
platformRequirements?: IAppStorePlatformRequirements;
|
|
218
|
+
/**
|
|
219
|
+
* Declares that this workload can consume platform-managed OIDC. The host
|
|
220
|
+
* still requires an explicit per-instance administrator toggle before it
|
|
221
|
+
* creates a client, injects credentials, or emits app-scoped role claims.
|
|
222
|
+
*/
|
|
223
|
+
platformOidc?: IAppStorePlatformOidcCapability;
|
|
200
224
|
minOneboxVersion?: string;
|
|
201
225
|
minCloudlyVersion?: string;
|
|
202
226
|
appStoreVersion?: string;
|
|
@@ -1,7 +1,82 @@
|
|
|
1
|
+
import { validateHostedAppRoleDefinitions, } from '../data/hostedapp.js';
|
|
1
2
|
export const appStoreStorageFeatureIds = {
|
|
2
3
|
bindingsV1: 'storage.bindings.v1',
|
|
3
4
|
filesystemV1: 'storage.filesystem.v1',
|
|
4
5
|
objectStorageV1: 'storage.object-storage.v1',
|
|
5
6
|
objectStorageSecretFileV1: 'storage.object-storage.secret-file.v1',
|
|
6
7
|
};
|
|
7
|
-
|
|
8
|
+
const appStoreEnvKeyRegex = /^[A-Z_][A-Z0-9_]*$/;
|
|
9
|
+
export const validateAppStorePlatformOidcCapability = (capabilityArg) => {
|
|
10
|
+
if (capabilityArg === undefined)
|
|
11
|
+
return [];
|
|
12
|
+
if (!capabilityArg || typeof capabilityArg !== 'object' || Array.isArray(capabilityArg)) {
|
|
13
|
+
return ['platformOidc must be an object'];
|
|
14
|
+
}
|
|
15
|
+
const capability = capabilityArg;
|
|
16
|
+
const errors = [];
|
|
17
|
+
if (typeof capability.redirectPath !== 'string'
|
|
18
|
+
|| !capability.redirectPath.startsWith('/')
|
|
19
|
+
|| capability.redirectPath.startsWith('//')
|
|
20
|
+
|| /[\\?#\s]/.test(capability.redirectPath)
|
|
21
|
+
|| /%5c/i.test(capability.redirectPath)
|
|
22
|
+
|| new URL(capability.redirectPath, 'https://app.invalid').pathname !== capability.redirectPath) {
|
|
23
|
+
errors.push('platformOidc.redirectPath must be a canonical same-origin path without query or fragment');
|
|
24
|
+
}
|
|
25
|
+
errors.push(...validateHostedAppRoleDefinitions(capability.roles)
|
|
26
|
+
.map((errorArg) => `platformOidc.${errorArg}`));
|
|
27
|
+
const environment = capability.environmentVariables;
|
|
28
|
+
if (!environment || typeof environment !== 'object' || Array.isArray(environment)) {
|
|
29
|
+
errors.push('platformOidc.environmentVariables must be an object');
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
const keys = ['issuerUrl', 'clientId', 'clientSecret', 'redirectUri', 'audience'];
|
|
33
|
+
const values = keys.map((keyArg) => environment[keyArg]);
|
|
34
|
+
keys.forEach((keyArg, indexArg) => {
|
|
35
|
+
if (typeof values[indexArg] !== 'string'
|
|
36
|
+
|| !appStoreEnvKeyRegex.test(values[indexArg])) {
|
|
37
|
+
errors.push(`platformOidc.environmentVariables.${keyArg} must be a valid environment key`);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
if (new Set(values).size !== values.length) {
|
|
41
|
+
errors.push('platformOidc environment keys must be unique');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (capability.clientAuthenticationMethod !== 'client_secret_basic'
|
|
45
|
+
&& capability.clientAuthenticationMethod !== 'client_secret_post') {
|
|
46
|
+
errors.push('platformOidc.clientAuthenticationMethod is unsupported');
|
|
47
|
+
}
|
|
48
|
+
return errors;
|
|
49
|
+
};
|
|
50
|
+
export const validateAppStoreVersionPlatformOidc = (configArg) => {
|
|
51
|
+
if (!configArg || typeof configArg !== 'object' || Array.isArray(configArg)) {
|
|
52
|
+
return ['appstore config must be an object'];
|
|
53
|
+
}
|
|
54
|
+
const config = configArg;
|
|
55
|
+
const errors = validateAppStorePlatformOidcCapability(config.platformOidc);
|
|
56
|
+
if (!config.platformOidc || typeof config.platformOidc !== 'object'
|
|
57
|
+
|| Array.isArray(config.platformOidc))
|
|
58
|
+
return errors;
|
|
59
|
+
const capability = config.platformOidc;
|
|
60
|
+
if (!capability.environmentVariables || typeof capability.environmentVariables !== 'object'
|
|
61
|
+
|| Array.isArray(capability.environmentVariables))
|
|
62
|
+
return errors;
|
|
63
|
+
const oidcKeys = new Set(Object.values(capability.environmentVariables)
|
|
64
|
+
.filter((valueArg) => typeof valueArg === 'string'));
|
|
65
|
+
const ordinaryEnvKeys = Array.isArray(config.envVars)
|
|
66
|
+
? config.envVars.map((envArg) => (envArg && typeof envArg === 'object' && !Array.isArray(envArg)
|
|
67
|
+
? envArg.key
|
|
68
|
+
: undefined)).filter((valueArg) => typeof valueArg === 'string')
|
|
69
|
+
: [];
|
|
70
|
+
const secretFileKeys = Array.isArray(config.secretFiles)
|
|
71
|
+
? config.secretFiles.map((fileArg) => (fileArg && typeof fileArg === 'object' && !Array.isArray(fileArg)
|
|
72
|
+
? fileArg.sourceKey
|
|
73
|
+
: undefined)).filter((valueArg) => typeof valueArg === 'string')
|
|
74
|
+
: [];
|
|
75
|
+
for (const key of [...ordinaryEnvKeys, ...secretFileKeys]) {
|
|
76
|
+
if (oidcKeys.has(key)) {
|
|
77
|
+
errors.push(`platformOidc environment key '${key}' collides with app runtime input`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return errors;
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9hcHBzdG9yZS90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQ0wsZ0NBQWdDLEdBRWpDLE1BQU0sc0JBQXNCLENBQUM7QUFpQzlCLE1BQU0sQ0FBQyxNQUFNLHlCQUF5QixHQUFHO0lBQ3ZDLFVBQVUsRUFBRSxxQkFBcUI7SUFDakMsWUFBWSxFQUFFLHVCQUF1QjtJQUNyQyxlQUFlLEVBQUUsMkJBQTJCO0lBQzVDLHlCQUF5QixFQUFFLHVDQUF1QztDQUMxRCxDQUFDO0FBK0pYLE1BQU0sbUJBQW1CLEdBQUcsb0JBQW9CLENBQUM7QUFFakQsTUFBTSxDQUFDLE1BQU0sc0NBQXNDLEdBQUcsQ0FDcEQsYUFBc0IsRUFDWixFQUFFO0lBQ1osSUFBSSxhQUFhLEtBQUssU0FBUztRQUFFLE9BQU8sRUFBRSxDQUFDO0lBQzNDLElBQUksQ0FBQyxhQUFhLElBQUksT0FBTyxhQUFhLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztRQUN4RixPQUFPLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBQ0QsTUFBTSxVQUFVLEdBQUcsYUFBd0MsQ0FBQztJQUM1RCxNQUFNLE1BQU0sR0FBYSxFQUFFLENBQUM7SUFDNUIsSUFBSSxPQUFPLFVBQVUsQ0FBQyxZQUFZLEtBQUssUUFBUTtXQUMxQyxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQztXQUN4QyxVQUFVLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUM7V0FDeEMsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDO1dBQ3hDLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQztXQUNwQyxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsWUFBWSxFQUFFLHFCQUFxQixDQUFDLENBQUMsUUFBUSxLQUFLLFVBQVUsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNsRyxNQUFNLENBQUMsSUFBSSxDQUFDLDBGQUEwRixDQUFDLENBQUM7SUFDMUcsQ0FBQztJQUNELE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxnQ0FBZ0MsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDO1NBQzlELEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsZ0JBQWdCLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUVsRCxNQUFNLFdBQVcsR0FBRyxVQUFVLENBQUMsb0JBQW9CLENBQUM7SUFDcEQsSUFBSSxDQUFDLFdBQVcsSUFBSSxPQUFPLFdBQVcsS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO1FBQ2xGLE1BQU0sQ0FBQyxJQUFJLENBQUMscURBQXFELENBQUMsQ0FBQztJQUNyRSxDQUFDO1NBQU0sQ0FBQztRQUNOLE1BQU0sSUFBSSxHQUFHLENBQUMsV0FBVyxFQUFFLFVBQVUsRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLFVBQVUsQ0FBVSxDQUFDO1FBQzNGLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFFLFdBQXVDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUN0RixJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxFQUFFO1lBQ2hDLElBQUksT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssUUFBUTttQkFDbkMsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBVyxDQUFDLEVBQUUsQ0FBQztnQkFDM0QsTUFBTSxDQUFDLElBQUksQ0FBQyxxQ0FBcUMsTUFBTSxrQ0FBa0MsQ0FBQyxDQUFDO1lBQzdGLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxLQUFLLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUMzQyxNQUFNLENBQUMsSUFBSSxDQUFDLDhDQUE4QyxDQUFDLENBQUM7UUFDOUQsQ0FBQztJQUNILENBQUM7SUFDRCxJQUFJLFVBQVUsQ0FBQywwQkFBMEIsS0FBSyxxQkFBcUI7V0FDOUQsVUFBVSxDQUFDLDBCQUEwQixLQUFLLG9CQUFvQixFQUFFLENBQUM7UUFDcEUsTUFBTSxDQUFDLElBQUksQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxtQ0FBbUMsR0FBRyxDQUNqRCxTQUFrQixFQUNSLEVBQUU7SUFDWixJQUFJLENBQUMsU0FBUyxJQUFJLE9BQU8sU0FBUyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7UUFDNUUsT0FBTyxDQUFDLG1DQUFtQyxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUNELE1BQU0sTUFBTSxHQUFHLFNBQW9DLENBQUM7SUFDcEQsTUFBTSxNQUFNLEdBQUcsc0NBQXNDLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQzNFLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxJQUFJLE9BQU8sTUFBTSxDQUFDLFlBQVksS0FBSyxRQUFRO1dBQzlELEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQztRQUFFLE9BQU8sTUFBTSxDQUFDO0lBQ3ZELE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxZQUF1QyxDQUFDO0lBQ2xFLElBQUksQ0FBQyxVQUFVLENBQUMsb0JBQW9CLElBQUksT0FBTyxVQUFVLENBQUMsb0JBQW9CLEtBQUssUUFBUTtXQUN0RixLQUFLLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxvQkFBb0IsQ0FBQztRQUFFLE9BQU8sTUFBTSxDQUFDO0lBQ25FLE1BQU0sUUFBUSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLG9CQUFvQixDQUFDO1NBQ3BFLE1BQU0sQ0FBQyxDQUFDLFFBQVEsRUFBc0IsRUFBRSxDQUFDLE9BQU8sUUFBUSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFDM0UsTUFBTSxlQUFlLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDO1FBQ25ELENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FDN0IsTUFBTSxJQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO1lBQzVELENBQUMsQ0FBRSxNQUFrQyxDQUFDLEdBQUc7WUFDekMsQ0FBQyxDQUFDLFNBQVMsQ0FDZCxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsUUFBUSxFQUFzQixFQUFFLENBQUMsT0FBTyxRQUFRLEtBQUssUUFBUSxDQUFDO1FBQzNFLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDUCxNQUFNLGNBQWMsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUM7UUFDdEQsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUNsQyxPQUFPLElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUM7WUFDL0QsQ0FBQyxDQUFFLE9BQW1DLENBQUMsU0FBUztZQUNoRCxDQUFDLENBQUMsU0FBUyxDQUNkLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxRQUFRLEVBQXNCLEVBQUUsQ0FBQyxPQUFPLFFBQVEsS0FBSyxRQUFRLENBQUM7UUFDM0UsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNQLEtBQUssTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLGVBQWUsRUFBRSxHQUFHLGNBQWMsQ0FBQyxFQUFFLENBQUM7UUFDMUQsSUFBSSxRQUFRLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDdEIsTUFBTSxDQUFDLElBQUksQ0FBQyxpQ0FBaUMsR0FBRyxtQ0FBbUMsQ0FBQyxDQUFDO1FBQ3ZGLENBQUM7SUFDSCxDQUFDO0lBQ0QsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQyxDQUFDIn0=
|
|
@@ -1,4 +1,75 @@
|
|
|
1
1
|
export type THostedAppHostType = 'onebox' | 'cloudly' | string;
|
|
2
|
+
export declare const hostedAppOidcRoleClaim: "roles";
|
|
3
|
+
export declare const hostedAppOidcAppInstanceIdClaim: "servezone_app_instance_id";
|
|
4
|
+
export interface IHostedAppRoleDefinition {
|
|
5
|
+
/** Stable role identifier emitted in the hosted app's audience-scoped token. */
|
|
6
|
+
id: string;
|
|
7
|
+
label: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface IHostedAppRoleAssignment {
|
|
11
|
+
/** Immutable hosted app instance identifier. Never use a mutable service name as this boundary. */
|
|
12
|
+
appInstanceId: string;
|
|
13
|
+
userId: string;
|
|
14
|
+
roleIds: string[];
|
|
15
|
+
assignedAt: number;
|
|
16
|
+
assignedByUserId: string;
|
|
17
|
+
}
|
|
18
|
+
export interface IHostedAppPlatformOidcClaims {
|
|
19
|
+
iss: string;
|
|
20
|
+
sub: string;
|
|
21
|
+
/** Mutable display name only. Never use this claim as identity authority. */
|
|
22
|
+
preferred_username: string;
|
|
23
|
+
aud: string;
|
|
24
|
+
iat: number;
|
|
25
|
+
exp: number;
|
|
26
|
+
auth_time: number;
|
|
27
|
+
nonce?: string;
|
|
28
|
+
[hostedAppOidcAppInstanceIdClaim]: string;
|
|
29
|
+
[hostedAppOidcRoleClaim]: string[];
|
|
30
|
+
}
|
|
31
|
+
interface IHostedAppPlatformOidcRegistrationBase {
|
|
32
|
+
/** Immutable OIDC client_id and ID-token audience for this hosted app. */
|
|
33
|
+
appInstanceId: string;
|
|
34
|
+
roleDefinitions: IHostedAppRoleDefinition[];
|
|
35
|
+
updatedAt: number;
|
|
36
|
+
}
|
|
37
|
+
type THostedAppRedirectUris = [string, ...string[]];
|
|
38
|
+
export type IHostedAppPlatformOidcRegistration = (IHostedAppPlatformOidcRegistrationBase & {
|
|
39
|
+
status: 'disabled';
|
|
40
|
+
redirectUris: [];
|
|
41
|
+
issuer?: never;
|
|
42
|
+
clientId?: never;
|
|
43
|
+
error?: never;
|
|
44
|
+
}) | (IHostedAppPlatformOidcRegistrationBase & {
|
|
45
|
+
status: 'enabling';
|
|
46
|
+
issuer: string;
|
|
47
|
+
clientId: string;
|
|
48
|
+
redirectUris: THostedAppRedirectUris;
|
|
49
|
+
error?: never;
|
|
50
|
+
}) | (IHostedAppPlatformOidcRegistrationBase & {
|
|
51
|
+
status: 'enabled' | 'disabling';
|
|
52
|
+
issuer: string;
|
|
53
|
+
clientId: string;
|
|
54
|
+
redirectUris: THostedAppRedirectUris;
|
|
55
|
+
error?: never;
|
|
56
|
+
}) | (IHostedAppPlatformOidcRegistrationBase & {
|
|
57
|
+
status: 'error';
|
|
58
|
+
redirectUris: string[];
|
|
59
|
+
issuer?: string;
|
|
60
|
+
clientId?: string;
|
|
61
|
+
error: string;
|
|
62
|
+
});
|
|
63
|
+
export declare const validateHostedAppRoleDefinitions: (rolesArg: unknown) => string[];
|
|
64
|
+
export declare const validateHostedAppPlatformOidcClaims: (claimsArg: unknown, expectedArg: {
|
|
65
|
+
issuer: string;
|
|
66
|
+
appInstanceId: string;
|
|
67
|
+
nonce?: string;
|
|
68
|
+
nowEpochSeconds?: number;
|
|
69
|
+
}) => string[];
|
|
70
|
+
export declare const validateHostedAppPlatformOidcRegistration: (registrationArg: unknown, expectedArg: {
|
|
71
|
+
appOrigin: string;
|
|
72
|
+
}) => string[];
|
|
2
73
|
export type THostedAppRuntimeStatus = 'starting' | 'running' | 'setupRequired' | 'degraded' | 'stopped' | 'unknown';
|
|
3
74
|
export type THostedAppBootstrapActionType = 'setupLink' | 'credentials' | 'message';
|
|
4
75
|
export type THostedAppBootstrapActionStatus = 'requested' | 'ready' | 'completed' | 'dismissed' | 'expired';
|
|
@@ -55,3 +126,4 @@ export interface IHostedAppLifecycleState extends IHostedAppLifecycleReport {
|
|
|
55
126
|
export type IHostedAppBootstrapActionRequest = Omit<IHostedAppBootstrapAction, 'id' | 'status' | 'createdAt' | 'updatedAt' | 'completedAt' | 'dismissedAt'> & {
|
|
56
127
|
id?: string;
|
|
57
128
|
};
|
|
129
|
+
export {};
|
|
@@ -1,2 +1,191 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
1
|
+
export const hostedAppOidcRoleClaim = 'roles';
|
|
2
|
+
export const hostedAppOidcAppInstanceIdClaim = 'servezone_app_instance_id';
|
|
3
|
+
const hostedAppRoleIdRegex = /^[a-z][a-z0-9:_-]{0,63}$/;
|
|
4
|
+
const hostedAppOpaqueIdRegex = /^[^\s\u0000-\u001f\u007f]{1,200}$/;
|
|
5
|
+
export const validateHostedAppRoleDefinitions = (rolesArg) => {
|
|
6
|
+
if (!Array.isArray(rolesArg) || rolesArg.length < 1 || rolesArg.length > 32) {
|
|
7
|
+
return ['roles must contain between 1 and 32 role definitions'];
|
|
8
|
+
}
|
|
9
|
+
const errors = [];
|
|
10
|
+
const roleIds = new Set();
|
|
11
|
+
rolesArg.forEach((roleArg, indexArg) => {
|
|
12
|
+
if (!roleArg || typeof roleArg !== 'object' || Array.isArray(roleArg)) {
|
|
13
|
+
errors.push(`role ${indexArg + 1} must be an object`);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const role = roleArg;
|
|
17
|
+
if (typeof role.id !== 'string' || !hostedAppRoleIdRegex.test(role.id)) {
|
|
18
|
+
errors.push(`role ${indexArg + 1} id must be a stable lowercase identifier`);
|
|
19
|
+
}
|
|
20
|
+
else if (roleIds.has(role.id)) {
|
|
21
|
+
errors.push(`role id '${role.id}' is duplicated`);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
roleIds.add(role.id);
|
|
25
|
+
}
|
|
26
|
+
if (typeof role.label !== 'string' || role.label.trim().length < 1 || role.label.length > 120) {
|
|
27
|
+
errors.push(`role ${indexArg + 1} label must contain between 1 and 120 characters`);
|
|
28
|
+
}
|
|
29
|
+
if (role.description !== undefined
|
|
30
|
+
&& (typeof role.description !== 'string' || role.description.length > 500)) {
|
|
31
|
+
errors.push(`role ${indexArg + 1} description must contain at most 500 characters`);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
return errors;
|
|
35
|
+
};
|
|
36
|
+
export const validateHostedAppPlatformOidcClaims = (claimsArg, expectedArg) => {
|
|
37
|
+
if (!claimsArg || typeof claimsArg !== 'object' || Array.isArray(claimsArg)) {
|
|
38
|
+
return ['OIDC claims must be an object'];
|
|
39
|
+
}
|
|
40
|
+
const claims = claimsArg;
|
|
41
|
+
const errors = [];
|
|
42
|
+
if (claims.iss !== expectedArg.issuer)
|
|
43
|
+
errors.push('OIDC issuer does not match');
|
|
44
|
+
if (claims.aud !== expectedArg.appInstanceId)
|
|
45
|
+
errors.push('OIDC audience does not match');
|
|
46
|
+
if (claims[hostedAppOidcAppInstanceIdClaim] !== expectedArg.appInstanceId) {
|
|
47
|
+
errors.push('OIDC app instance does not match the audience');
|
|
48
|
+
}
|
|
49
|
+
if (typeof claims.sub !== 'string' || claims.sub.length === 0) {
|
|
50
|
+
errors.push('OIDC subject is missing or malformed');
|
|
51
|
+
}
|
|
52
|
+
if (typeof claims.preferred_username !== 'string'
|
|
53
|
+
|| claims.preferred_username.trim().length === 0) {
|
|
54
|
+
errors.push('OIDC preferred username is missing or malformed');
|
|
55
|
+
}
|
|
56
|
+
const now = expectedArg.nowEpochSeconds ?? Math.floor(Date.now() / 1000);
|
|
57
|
+
if (!Number.isSafeInteger(claims.iat) || claims.iat < 0) {
|
|
58
|
+
errors.push('OIDC issued-at time is missing or malformed');
|
|
59
|
+
}
|
|
60
|
+
if (!Number.isSafeInteger(claims.exp) || claims.exp <= now) {
|
|
61
|
+
errors.push('OIDC token is expired or has malformed expiry');
|
|
62
|
+
}
|
|
63
|
+
if (!Number.isSafeInteger(claims.auth_time)
|
|
64
|
+
|| claims.auth_time < 0
|
|
65
|
+
|| claims.auth_time > now) {
|
|
66
|
+
errors.push('OIDC authentication time is missing or malformed');
|
|
67
|
+
}
|
|
68
|
+
if (expectedArg.nonce !== undefined && claims.nonce !== expectedArg.nonce) {
|
|
69
|
+
errors.push('OIDC nonce does not match');
|
|
70
|
+
}
|
|
71
|
+
const roles = claims[hostedAppOidcRoleClaim];
|
|
72
|
+
if (!Array.isArray(roles) || roles.length < 1 || roles.length > 32) {
|
|
73
|
+
errors.push('OIDC roles must be an array with between 1 and 32 entries');
|
|
74
|
+
}
|
|
75
|
+
else if (roles.some((roleArg) => typeof roleArg !== 'string'
|
|
76
|
+
|| !hostedAppRoleIdRegex.test(roleArg))
|
|
77
|
+
|| new Set(roles).size !== roles.length) {
|
|
78
|
+
errors.push('OIDC roles contain malformed or duplicate identifiers');
|
|
79
|
+
}
|
|
80
|
+
return errors;
|
|
81
|
+
};
|
|
82
|
+
export const validateHostedAppPlatformOidcRegistration = (registrationArg, expectedArg) => {
|
|
83
|
+
if (!registrationArg || typeof registrationArg !== 'object'
|
|
84
|
+
|| Array.isArray(registrationArg)) {
|
|
85
|
+
return ['OIDC registration must be an object'];
|
|
86
|
+
}
|
|
87
|
+
const registration = registrationArg;
|
|
88
|
+
const errors = [];
|
|
89
|
+
let expectedOrigin;
|
|
90
|
+
try {
|
|
91
|
+
const parsedAppOrigin = new URL(expectedArg.appOrigin);
|
|
92
|
+
if (parsedAppOrigin.protocol !== 'https:'
|
|
93
|
+
|| parsedAppOrigin.username
|
|
94
|
+
|| parsedAppOrigin.password
|
|
95
|
+
|| parsedAppOrigin.origin !== expectedArg.appOrigin) {
|
|
96
|
+
errors.push('Expected OIDC app origin must be a canonical credential-free HTTPS origin');
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
expectedOrigin = parsedAppOrigin.origin;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
errors.push('Expected OIDC app origin must be an absolute URL origin');
|
|
104
|
+
}
|
|
105
|
+
if (typeof registration.appInstanceId !== 'string'
|
|
106
|
+
|| !hostedAppOpaqueIdRegex.test(registration.appInstanceId)) {
|
|
107
|
+
errors.push('OIDC registration appInstanceId is missing or malformed');
|
|
108
|
+
}
|
|
109
|
+
const statuses = ['disabled', 'enabling', 'enabled', 'disabling', 'error'];
|
|
110
|
+
if (typeof registration.status !== 'string' || !statuses.includes(registration.status)) {
|
|
111
|
+
errors.push('OIDC registration status is unsupported');
|
|
112
|
+
}
|
|
113
|
+
errors.push(...validateHostedAppRoleDefinitions(registration.roleDefinitions)
|
|
114
|
+
.map((errorArg) => `OIDC registration ${errorArg}`));
|
|
115
|
+
if (!Number.isSafeInteger(registration.updatedAt) || registration.updatedAt < 0) {
|
|
116
|
+
errors.push('OIDC registration updatedAt is missing or malformed');
|
|
117
|
+
}
|
|
118
|
+
const redirectUris = registration.redirectUris;
|
|
119
|
+
if (!Array.isArray(redirectUris)
|
|
120
|
+
|| redirectUris.length > 8
|
|
121
|
+
|| redirectUris.some((uriArg) => typeof uriArg !== 'string')) {
|
|
122
|
+
errors.push('OIDC registration redirectUris are malformed');
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
if (registration.status === 'disabled' && redirectUris.length !== 0) {
|
|
126
|
+
errors.push('Disabled OIDC registration must not retain redirect URIs');
|
|
127
|
+
}
|
|
128
|
+
if (registration.status !== 'disabled'
|
|
129
|
+
&& registration.status !== 'error'
|
|
130
|
+
&& redirectUris.length < 1) {
|
|
131
|
+
errors.push('Active OIDC registration requires a redirect URI');
|
|
132
|
+
}
|
|
133
|
+
if (new Set(redirectUris).size !== redirectUris.length) {
|
|
134
|
+
errors.push('OIDC registration redirect URIs must be unique');
|
|
135
|
+
}
|
|
136
|
+
for (const redirectUri of redirectUris) {
|
|
137
|
+
try {
|
|
138
|
+
const parsed = new URL(redirectUri);
|
|
139
|
+
if (parsed.protocol !== 'https:'
|
|
140
|
+
|| parsed.username
|
|
141
|
+
|| parsed.password
|
|
142
|
+
|| parsed.search
|
|
143
|
+
|| parsed.hash
|
|
144
|
+
|| parsed.toString() !== redirectUri) {
|
|
145
|
+
errors.push('OIDC registration redirect URIs must be canonical credential-free HTTPS URLs without query or fragment');
|
|
146
|
+
}
|
|
147
|
+
if (expectedOrigin && parsed.origin !== expectedOrigin) {
|
|
148
|
+
errors.push('OIDC registration redirect URIs must use the app origin');
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
errors.push('OIDC registration redirect URIs must be absolute URLs');
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const requiresIssuer = registration.status === 'enabling'
|
|
157
|
+
|| registration.status === 'enabled'
|
|
158
|
+
|| registration.status === 'disabling';
|
|
159
|
+
if (requiresIssuer || registration.issuer !== undefined) {
|
|
160
|
+
try {
|
|
161
|
+
const issuer = new URL(registration.issuer);
|
|
162
|
+
if (issuer.protocol !== 'https:' || issuer.username || issuer.password
|
|
163
|
+
|| issuer.search || issuer.hash) {
|
|
164
|
+
errors.push('OIDC registration issuer must be a credential-free HTTPS URL without query or fragment');
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
errors.push('OIDC registration issuer must be an absolute URL');
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const requiresClientId = registration.status === 'enabling'
|
|
172
|
+
|| registration.status === 'enabled'
|
|
173
|
+
|| registration.status === 'disabling';
|
|
174
|
+
if (registration.status === 'disabled'
|
|
175
|
+
&& (registration.issuer !== undefined || registration.clientId !== undefined)) {
|
|
176
|
+
errors.push('Disabled OIDC registration must not retain issuer or client metadata');
|
|
177
|
+
}
|
|
178
|
+
if (requiresClientId && registration.clientId !== registration.appInstanceId) {
|
|
179
|
+
errors.push('OIDC registration clientId must equal appInstanceId');
|
|
180
|
+
}
|
|
181
|
+
else if (registration.clientId !== undefined
|
|
182
|
+
&& registration.clientId !== registration.appInstanceId) {
|
|
183
|
+
errors.push('OIDC registration clientId must equal appInstanceId when present');
|
|
184
|
+
}
|
|
185
|
+
if (registration.status === 'error'
|
|
186
|
+
&& (typeof registration.error !== 'string' || registration.error.length < 1)) {
|
|
187
|
+
errors.push('Errored OIDC registration requires an error message');
|
|
188
|
+
}
|
|
189
|
+
return errors;
|
|
190
|
+
};
|
|
191
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG9zdGVkYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvZGF0YS9ob3N0ZWRhcHAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsT0FBZ0IsQ0FBQztBQUN2RCxNQUFNLENBQUMsTUFBTSwrQkFBK0IsR0FBRywyQkFBb0MsQ0FBQztBQXVFcEYsTUFBTSxvQkFBb0IsR0FBRywwQkFBMEIsQ0FBQztBQUN4RCxNQUFNLHNCQUFzQixHQUFHLG1DQUFtQyxDQUFDO0FBRW5FLE1BQU0sQ0FBQyxNQUFNLGdDQUFnQyxHQUFHLENBQzlDLFFBQWlCLEVBQ1AsRUFBRTtJQUNaLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxNQUFNLEdBQUcsRUFBRSxFQUFFLENBQUM7UUFDNUUsT0FBTyxDQUFDLHNEQUFzRCxDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUNELE1BQU0sTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUM1QixNQUFNLE9BQU8sR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO0lBQ2xDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLEVBQUU7UUFDckMsSUFBSSxDQUFDLE9BQU8sSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ3RFLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxRQUFRLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1lBQ3RELE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxJQUFJLEdBQUcsT0FBa0MsQ0FBQztRQUNoRCxJQUFJLE9BQU8sSUFBSSxDQUFDLEVBQUUsS0FBSyxRQUFRLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxD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
|
|
@@ -8,6 +8,8 @@ export type TRuntimeImageVerificationStatus = 'not-required' | 'pending' | 'veri
|
|
|
8
8
|
export type TImmutableImageRolloutStatus = 'pending' | 'deploying' | 'verifying' | 'succeeded' | 'failed' | 'mismatched' | 'rolling-back' | 'rolled-back';
|
|
9
9
|
export interface ICoreflowRuntimeCapabilities {
|
|
10
10
|
immutableImageDeploymentVersion: 1;
|
|
11
|
+
/** Coreflow can answer the versioned, node-scoped Corestore inventory probe. */
|
|
12
|
+
corestoreInventoryVersion?: 1;
|
|
11
13
|
}
|
|
12
14
|
/**
|
|
13
15
|
* A registry manifest observed by Cloudly. Observation alone does not make the
|
|
@@ -245,4 +245,4 @@ export const validateImageRolloutStatus = (statusArg) => {
|
|
|
245
245
|
}
|
|
246
246
|
return errors;
|
|
247
247
|
};
|
|
248
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1tdXRhYmxlaW1hZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2ltbXV0YWJsZWltYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQW9HQSxNQUFNLENBQUMsTUFBTSxpQ0FBaUMsR0FBRyxDQUFDLE9BVWpELEVBQWlFLEVBQUU7SUFDbEUsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLFdBQXlDLEVBQUUsRUFBRSxDQUFDO1FBQ3pFLFdBQVcsQ0FBQyxNQUFNO1FBQ2xCLFdBQVcsQ0FBQyxVQUFVO1FBQ3RCLFdBQVcsQ0FBQyxXQUFXO1FBQ3ZCLFdBQVcsQ0FBQyxXQUFXO1FBQ3ZCLFdBQVcsQ0FBQyxZQUFZO1FBQ3hCLFdBQVcsQ0FBQyxVQUFVO1FBQ3RCLFdBQVcsQ0FBQyxHQUFHO1FBQ2YsV0FBVyxDQUFDLGtCQUFrQjtRQUM5QixXQUFXLENBQUMsaUJBQWlCO1FBQzdCLFdBQVcsQ0FBQyxVQUFVO0tBQ3ZCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2pCLE1BQU0sY0FBYyxHQUFHLElBQUksR0FBRyxFQUF3QyxDQUFDO0lBQ3ZFLE1BQU0sTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUM1QixLQUFLLE1BQU0sUUFBUSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGVBQWUsSUFBSSxFQUFFLEVBQUUsQ0FBQztRQUNsRSxNQUFNLFFBQVEsR0FBRyxjQUFjLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUN6RCxJQUFJLFFBQVEsSUFBSSxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsS0FBSyxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQ2hGLE1BQU0sQ0FBQyxJQUFJLENBQUMsb0RBQW9ELENBQUMsQ0FBQztRQUNwRSxDQUFDO2FBQU0sQ0FBQztZQUNOLGNBQWMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FB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
|
|
248
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1tdXRhYmxlaW1hZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2ltbXV0YWJsZWltYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQXNHQSxNQUFNLENBQUMsTUFBTSxpQ0FBaUMsR0FBRyxDQUFDLE9BVWpELEVBQWlFLEVBQUU7SUFDbEUsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLFdBQXlDLEVBQUUsRUFBRSxDQUFDO1FBQ3pFLFdBQVcsQ0FBQyxNQUFNO1FBQ2xCLFdBQVcsQ0FBQyxVQUFVO1FBQ3RCLFdBQVcsQ0FBQyxXQUFXO1FBQ3ZCLFdBQVcsQ0FBQyxXQUFXO1FBQ3ZCLFdBQVcsQ0FBQyxZQUFZO1FBQ3hCLFdBQVcsQ0FBQyxVQUFVO1FBQ3RCLFdBQVcsQ0FBQyxHQUFHO1FBQ2YsV0FBVyxDQUFDLGtCQUFrQjtRQUM5QixXQUFXLENBQUMsaUJBQWlCO1FBQzdCLFdBQVcsQ0FBQyxVQUFVO0tBQ3ZCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2pCLE1BQU0sY0FBYyxHQUFHLElBQUksR0FBRyxFQUF3QyxDQUFDO0lBQ3ZFLE1BQU0sTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUM1QixLQUFLLE1BQU0sUUFBUSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGVBQWUsSUFBSSxFQUFFLEVBQUUsQ0FBQztRQUNsRSxNQUFNLFFBQVEsR0FBRyxjQUFjLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUN6RCxJQUFJLFFBQVEsSUFBSSxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsS0FBSyxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQ2hGLE1BQU0sQ0FBQyxJQUFJLENBQUMsb0RBQW9ELENBQUMsQ0FBQztRQUNwRSxDQUFDO2FBQU0sQ0FBQztZQUNOLGNBQWMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FB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
|
|
@@ -23,18 +23,52 @@ export interface ICorestoreServiceResources {
|
|
|
23
23
|
export interface ICorestoreNodeInventory {
|
|
24
24
|
/** Swarm node hostnames of the reporting coreflow. */
|
|
25
25
|
nodeNames: string[];
|
|
26
|
+
protocolVersion: 1;
|
|
27
|
+
checkedAt: number;
|
|
26
28
|
reachable: boolean;
|
|
29
|
+
errorCode?: 'NODE_DISCOVERY_FAILED' | 'CORESTORE_UNREACHABLE';
|
|
27
30
|
error?: string;
|
|
28
31
|
services: ICorestoreServiceResources[];
|
|
29
32
|
}
|
|
33
|
+
export type TCorestoreInventoryProbeStatus = 'ok' | 'connection-missing' | 'connection-inspection-failed' | 'identity-unverified' | 'node-tag-missing' | 'connection-ambiguous' | 'handler-unsupported' | 'rpc-timeout' | 'rpc-rejected' | 'rpc-invalid-response' | 'node-identity-mismatch' | 'corestore-unreachable';
|
|
34
|
+
/**
|
|
35
|
+
* Cloudly's control-plane view of one expected node. Every expected online
|
|
36
|
+
* node receives exactly one probe result, including transport and registration
|
|
37
|
+
* failures that used to disappear from the inventory array.
|
|
38
|
+
*/
|
|
39
|
+
export interface ICorestoreInventoryProbe {
|
|
40
|
+
expectedNodeName: string;
|
|
41
|
+
expectedClusterId?: string;
|
|
42
|
+
processRunning?: boolean;
|
|
43
|
+
cloudlyRegistered: boolean;
|
|
44
|
+
inventoryRpcReady: boolean;
|
|
45
|
+
status: TCorestoreInventoryProbeStatus;
|
|
46
|
+
connectionId?: string;
|
|
47
|
+
reporterSessionId?: string;
|
|
48
|
+
capabilityVersion?: number;
|
|
49
|
+
observedNodeNames: string[];
|
|
50
|
+
checkedAt: number;
|
|
51
|
+
lastSuccessfulInventoryAt?: number;
|
|
52
|
+
message?: string;
|
|
53
|
+
inventory?: ICorestoreNodeInventory;
|
|
54
|
+
}
|
|
55
|
+
export interface ICorestoreInventoryReport {
|
|
56
|
+
checkedAt: number;
|
|
57
|
+
inventories: ICorestoreNodeInventory[];
|
|
58
|
+
probes: ICorestoreInventoryProbe[];
|
|
59
|
+
}
|
|
60
|
+
/** Final registration tag restored only after identity and capability tags. */
|
|
61
|
+
export interface ICoreflowInventoryRegistration {
|
|
62
|
+
registrationVersion: 1;
|
|
63
|
+
reporterSessionId: string;
|
|
64
|
+
registeredAt: number;
|
|
65
|
+
}
|
|
30
66
|
export interface IReq_Any_Cloudly_GetCorestoreInventory extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Any_Cloudly_GetCorestoreInventory> {
|
|
31
67
|
method: 'getCorestoreInventory';
|
|
32
68
|
request: {
|
|
33
69
|
identity: IIdentity;
|
|
34
70
|
};
|
|
35
|
-
response:
|
|
36
|
-
inventories: ICorestoreNodeInventory[];
|
|
37
|
-
};
|
|
71
|
+
response: ICorestoreInventoryReport;
|
|
38
72
|
}
|
|
39
73
|
export interface IReq_Cloudly_Coreflow_GetCorestoreInventory extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_Cloudly_Coreflow_GetCorestoreInventory> {
|
|
40
74
|
method: 'coreflowGetCorestoreInventory';
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -208,6 +208,45 @@ if (webTarget && data.isHttpServiceTargetProtocol(webTarget.protocol)) {
|
|
|
208
208
|
|
|
209
209
|
`normalizeServicePortData()` returns service data with canonical `targetPorts`, domain `targetPort` refs, and `publicPortMappings` while removing legacy domain `port` fields from normalized writes.
|
|
210
210
|
|
|
211
|
+
## Hosted-App Authorization and Platform OIDC
|
|
212
|
+
|
|
213
|
+
An App Store version can declare that it supports platform-managed OpenID Connect. This is a capability declaration only: Onebox and Cloudly keep OIDC disabled until an administrator explicitly enables it for that exact app instance, and they can disable it again without changing the template.
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import { appstore } from '@serve.zone/interfaces';
|
|
217
|
+
|
|
218
|
+
const config: appstore.IAppStoreVersionConfig = {
|
|
219
|
+
image: 'registry.example.com/example/app:1.0.0',
|
|
220
|
+
platformOidc: {
|
|
221
|
+
redirectPath: '/auth/oidc/callback',
|
|
222
|
+
roles: [
|
|
223
|
+
{ id: 'admin', label: 'Administrator' },
|
|
224
|
+
{ id: 'user', label: 'User' },
|
|
225
|
+
],
|
|
226
|
+
environmentVariables: {
|
|
227
|
+
issuerUrl: 'SERVEZONE_PLATFORM_OIDC_ISSUER',
|
|
228
|
+
clientId: 'SERVEZONE_PLATFORM_OIDC_CLIENT_ID',
|
|
229
|
+
clientSecret: 'SERVEZONE_PLATFORM_OIDC_CLIENT_SECRET',
|
|
230
|
+
redirectUri: 'SERVEZONE_PLATFORM_OIDC_REDIRECT_URI',
|
|
231
|
+
audience: 'SERVEZONE_PLATFORM_OIDC_AUDIENCE',
|
|
232
|
+
},
|
|
233
|
+
clientAuthenticationMethod: 'client_secret_basic',
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`redirectPath` is a canonical callback path on the app's HTTPS origin. Registration validation also requires that canonical app origin explicitly and rejects cross-origin, normalized, query-bearing, fragment-bearing, or duplicate callback URLs. The five environment values are environment-key names, not credentials embedded in the manifest. A host injects the generated client secret through its secret environment path and injects the other registration values only while OIDC is enabled.
|
|
239
|
+
|
|
240
|
+
`data.IHostedAppRoleAssignment` binds a stable user subject to an immutable `appInstanceId`. That same app instance is the OIDC `client_id`, the ID-token `aud`, and the `servezone_app_instance_id` claim. Tokens include only the assigned roles for that audience; `preferred_username` is display metadata and must not be treated as identity authority.
|
|
241
|
+
|
|
242
|
+
Validate untrusted manifests, registrations, and claims with:
|
|
243
|
+
|
|
244
|
+
- `data.validateHostedAppRoleDefinitions`
|
|
245
|
+
- `data.validateHostedAppPlatformOidcRegistration`
|
|
246
|
+
- `data.validateHostedAppPlatformOidcClaims`
|
|
247
|
+
- `appstore.validateAppStorePlatformOidcCapability`
|
|
248
|
+
- `appstore.validateAppStoreVersionPlatformOidc`
|
|
249
|
+
|
|
211
250
|
## TypedRequest Contracts
|
|
212
251
|
|
|
213
252
|
Use `requests` when registering handlers with `@api.global/typedrequest` or when creating typed requests through a TypedSocket client.
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/appstore/types.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { IServiceSecretFile } from '../data/service.js';
|
|
2
|
+
import {
|
|
3
|
+
validateHostedAppRoleDefinitions,
|
|
4
|
+
type IHostedAppRoleDefinition,
|
|
5
|
+
} from '../data/hostedapp.js';
|
|
2
6
|
import type {
|
|
3
7
|
IServiceDomainRoute,
|
|
4
8
|
IServicePublicPortMapping,
|
|
@@ -178,6 +182,105 @@ export interface IAppStorePublishedPort {
|
|
|
178
182
|
hostIp?: string;
|
|
179
183
|
}
|
|
180
184
|
|
|
185
|
+
export interface IAppStorePlatformOidcEnvironmentVariables {
|
|
186
|
+
issuerUrl: string;
|
|
187
|
+
clientId: string;
|
|
188
|
+
/** The hosting platform must deliver this value through its secret environment path. */
|
|
189
|
+
clientSecret: string;
|
|
190
|
+
redirectUri: string;
|
|
191
|
+
audience: string;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface IAppStorePlatformOidcCapability {
|
|
195
|
+
/** Callback path relative to the app's canonical HTTPS origin. */
|
|
196
|
+
redirectPath: string;
|
|
197
|
+
roles: IHostedAppRoleDefinition[];
|
|
198
|
+
environmentVariables: IAppStorePlatformOidcEnvironmentVariables;
|
|
199
|
+
clientAuthenticationMethod: 'client_secret_basic' | 'client_secret_post';
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const appStoreEnvKeyRegex = /^[A-Z_][A-Z0-9_]*$/;
|
|
203
|
+
|
|
204
|
+
export const validateAppStorePlatformOidcCapability = (
|
|
205
|
+
capabilityArg: unknown,
|
|
206
|
+
): string[] => {
|
|
207
|
+
if (capabilityArg === undefined) return [];
|
|
208
|
+
if (!capabilityArg || typeof capabilityArg !== 'object' || Array.isArray(capabilityArg)) {
|
|
209
|
+
return ['platformOidc must be an object'];
|
|
210
|
+
}
|
|
211
|
+
const capability = capabilityArg as Record<string, unknown>;
|
|
212
|
+
const errors: string[] = [];
|
|
213
|
+
if (typeof capability.redirectPath !== 'string'
|
|
214
|
+
|| !capability.redirectPath.startsWith('/')
|
|
215
|
+
|| capability.redirectPath.startsWith('//')
|
|
216
|
+
|| /[\\?#\s]/.test(capability.redirectPath)
|
|
217
|
+
|| /%5c/i.test(capability.redirectPath)
|
|
218
|
+
|| new URL(capability.redirectPath, 'https://app.invalid').pathname !== capability.redirectPath) {
|
|
219
|
+
errors.push('platformOidc.redirectPath must be a canonical same-origin path without query or fragment');
|
|
220
|
+
}
|
|
221
|
+
errors.push(...validateHostedAppRoleDefinitions(capability.roles)
|
|
222
|
+
.map((errorArg) => `platformOidc.${errorArg}`));
|
|
223
|
+
|
|
224
|
+
const environment = capability.environmentVariables;
|
|
225
|
+
if (!environment || typeof environment !== 'object' || Array.isArray(environment)) {
|
|
226
|
+
errors.push('platformOidc.environmentVariables must be an object');
|
|
227
|
+
} else {
|
|
228
|
+
const keys = ['issuerUrl', 'clientId', 'clientSecret', 'redirectUri', 'audience'] as const;
|
|
229
|
+
const values = keys.map((keyArg) => (environment as Record<string, unknown>)[keyArg]);
|
|
230
|
+
keys.forEach((keyArg, indexArg) => {
|
|
231
|
+
if (typeof values[indexArg] !== 'string'
|
|
232
|
+
|| !appStoreEnvKeyRegex.test(values[indexArg] as string)) {
|
|
233
|
+
errors.push(`platformOidc.environmentVariables.${keyArg} must be a valid environment key`);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
if (new Set(values).size !== values.length) {
|
|
237
|
+
errors.push('platformOidc environment keys must be unique');
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (capability.clientAuthenticationMethod !== 'client_secret_basic'
|
|
241
|
+
&& capability.clientAuthenticationMethod !== 'client_secret_post') {
|
|
242
|
+
errors.push('platformOidc.clientAuthenticationMethod is unsupported');
|
|
243
|
+
}
|
|
244
|
+
return errors;
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
export const validateAppStoreVersionPlatformOidc = (
|
|
248
|
+
configArg: unknown,
|
|
249
|
+
): string[] => {
|
|
250
|
+
if (!configArg || typeof configArg !== 'object' || Array.isArray(configArg)) {
|
|
251
|
+
return ['appstore config must be an object'];
|
|
252
|
+
}
|
|
253
|
+
const config = configArg as Record<string, unknown>;
|
|
254
|
+
const errors = validateAppStorePlatformOidcCapability(config.platformOidc);
|
|
255
|
+
if (!config.platformOidc || typeof config.platformOidc !== 'object'
|
|
256
|
+
|| Array.isArray(config.platformOidc)) return errors;
|
|
257
|
+
const capability = config.platformOidc as Record<string, unknown>;
|
|
258
|
+
if (!capability.environmentVariables || typeof capability.environmentVariables !== 'object'
|
|
259
|
+
|| Array.isArray(capability.environmentVariables)) return errors;
|
|
260
|
+
const oidcKeys = new Set(Object.values(capability.environmentVariables)
|
|
261
|
+
.filter((valueArg): valueArg is string => typeof valueArg === 'string'));
|
|
262
|
+
const ordinaryEnvKeys = Array.isArray(config.envVars)
|
|
263
|
+
? config.envVars.map((envArg) => (
|
|
264
|
+
envArg && typeof envArg === 'object' && !Array.isArray(envArg)
|
|
265
|
+
? (envArg as Record<string, unknown>).key
|
|
266
|
+
: undefined
|
|
267
|
+
)).filter((valueArg): valueArg is string => typeof valueArg === 'string')
|
|
268
|
+
: [];
|
|
269
|
+
const secretFileKeys = Array.isArray(config.secretFiles)
|
|
270
|
+
? config.secretFiles.map((fileArg) => (
|
|
271
|
+
fileArg && typeof fileArg === 'object' && !Array.isArray(fileArg)
|
|
272
|
+
? (fileArg as Record<string, unknown>).sourceKey
|
|
273
|
+
: undefined
|
|
274
|
+
)).filter((valueArg): valueArg is string => typeof valueArg === 'string')
|
|
275
|
+
: [];
|
|
276
|
+
for (const key of [...ordinaryEnvKeys, ...secretFileKeys]) {
|
|
277
|
+
if (oidcKeys.has(key)) {
|
|
278
|
+
errors.push(`platformOidc environment key '${key}' collides with app runtime input`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return errors;
|
|
282
|
+
};
|
|
283
|
+
|
|
181
284
|
export interface IAppStoreApp {
|
|
182
285
|
id: string;
|
|
183
286
|
name: string;
|
|
@@ -246,6 +349,12 @@ export interface IAppStoreVersionConfig {
|
|
|
246
349
|
storageRequests?: TAppStoreStorageRequest[];
|
|
247
350
|
publishedPorts?: IAppStorePublishedPort[];
|
|
248
351
|
platformRequirements?: IAppStorePlatformRequirements;
|
|
352
|
+
/**
|
|
353
|
+
* Declares that this workload can consume platform-managed OIDC. The host
|
|
354
|
+
* still requires an explicit per-instance administrator toggle before it
|
|
355
|
+
* creates a client, injects credentials, or emits app-scoped role claims.
|
|
356
|
+
*/
|
|
357
|
+
platformOidc?: IAppStorePlatformOidcCapability;
|
|
249
358
|
minOneboxVersion?: string;
|
|
250
359
|
minCloudlyVersion?: string;
|
|
251
360
|
appStoreVersion?: string;
|
package/ts/data/hostedapp.ts
CHANGED
|
@@ -1,5 +1,273 @@
|
|
|
1
1
|
export type THostedAppHostType = 'onebox' | 'cloudly' | string;
|
|
2
2
|
|
|
3
|
+
export const hostedAppOidcRoleClaim = 'roles' as const;
|
|
4
|
+
export const hostedAppOidcAppInstanceIdClaim = 'servezone_app_instance_id' as const;
|
|
5
|
+
|
|
6
|
+
export interface IHostedAppRoleDefinition {
|
|
7
|
+
/** Stable role identifier emitted in the hosted app's audience-scoped token. */
|
|
8
|
+
id: string;
|
|
9
|
+
label: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface IHostedAppRoleAssignment {
|
|
14
|
+
/** Immutable hosted app instance identifier. Never use a mutable service name as this boundary. */
|
|
15
|
+
appInstanceId: string;
|
|
16
|
+
userId: string;
|
|
17
|
+
roleIds: string[];
|
|
18
|
+
assignedAt: number;
|
|
19
|
+
assignedByUserId: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface IHostedAppPlatformOidcClaims {
|
|
23
|
+
iss: string;
|
|
24
|
+
sub: string;
|
|
25
|
+
/** Mutable display name only. Never use this claim as identity authority. */
|
|
26
|
+
preferred_username: string;
|
|
27
|
+
aud: string;
|
|
28
|
+
iat: number;
|
|
29
|
+
exp: number;
|
|
30
|
+
auth_time: number;
|
|
31
|
+
nonce?: string;
|
|
32
|
+
[hostedAppOidcAppInstanceIdClaim]: string;
|
|
33
|
+
[hostedAppOidcRoleClaim]: string[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface IHostedAppPlatformOidcRegistrationBase {
|
|
37
|
+
/** Immutable OIDC client_id and ID-token audience for this hosted app. */
|
|
38
|
+
appInstanceId: string;
|
|
39
|
+
roleDefinitions: IHostedAppRoleDefinition[];
|
|
40
|
+
updatedAt: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type THostedAppRedirectUris = [string, ...string[]];
|
|
44
|
+
|
|
45
|
+
export type IHostedAppPlatformOidcRegistration =
|
|
46
|
+
| (IHostedAppPlatformOidcRegistrationBase & {
|
|
47
|
+
status: 'disabled';
|
|
48
|
+
redirectUris: [];
|
|
49
|
+
issuer?: never;
|
|
50
|
+
clientId?: never;
|
|
51
|
+
error?: never;
|
|
52
|
+
})
|
|
53
|
+
| (IHostedAppPlatformOidcRegistrationBase & {
|
|
54
|
+
status: 'enabling';
|
|
55
|
+
issuer: string;
|
|
56
|
+
clientId: string;
|
|
57
|
+
redirectUris: THostedAppRedirectUris;
|
|
58
|
+
error?: never;
|
|
59
|
+
})
|
|
60
|
+
| (IHostedAppPlatformOidcRegistrationBase & {
|
|
61
|
+
status: 'enabled' | 'disabling';
|
|
62
|
+
issuer: string;
|
|
63
|
+
clientId: string;
|
|
64
|
+
redirectUris: THostedAppRedirectUris;
|
|
65
|
+
error?: never;
|
|
66
|
+
})
|
|
67
|
+
| (IHostedAppPlatformOidcRegistrationBase & {
|
|
68
|
+
status: 'error';
|
|
69
|
+
redirectUris: string[];
|
|
70
|
+
issuer?: string;
|
|
71
|
+
clientId?: string;
|
|
72
|
+
error: string;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const hostedAppRoleIdRegex = /^[a-z][a-z0-9:_-]{0,63}$/;
|
|
76
|
+
const hostedAppOpaqueIdRegex = /^[^\s\u0000-\u001f\u007f]{1,200}$/;
|
|
77
|
+
|
|
78
|
+
export const validateHostedAppRoleDefinitions = (
|
|
79
|
+
rolesArg: unknown,
|
|
80
|
+
): string[] => {
|
|
81
|
+
if (!Array.isArray(rolesArg) || rolesArg.length < 1 || rolesArg.length > 32) {
|
|
82
|
+
return ['roles must contain between 1 and 32 role definitions'];
|
|
83
|
+
}
|
|
84
|
+
const errors: string[] = [];
|
|
85
|
+
const roleIds = new Set<string>();
|
|
86
|
+
rolesArg.forEach((roleArg, indexArg) => {
|
|
87
|
+
if (!roleArg || typeof roleArg !== 'object' || Array.isArray(roleArg)) {
|
|
88
|
+
errors.push(`role ${indexArg + 1} must be an object`);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const role = roleArg as Record<string, unknown>;
|
|
92
|
+
if (typeof role.id !== 'string' || !hostedAppRoleIdRegex.test(role.id)) {
|
|
93
|
+
errors.push(`role ${indexArg + 1} id must be a stable lowercase identifier`);
|
|
94
|
+
} else if (roleIds.has(role.id)) {
|
|
95
|
+
errors.push(`role id '${role.id}' is duplicated`);
|
|
96
|
+
} else {
|
|
97
|
+
roleIds.add(role.id);
|
|
98
|
+
}
|
|
99
|
+
if (typeof role.label !== 'string' || role.label.trim().length < 1 || role.label.length > 120) {
|
|
100
|
+
errors.push(`role ${indexArg + 1} label must contain between 1 and 120 characters`);
|
|
101
|
+
}
|
|
102
|
+
if (role.description !== undefined
|
|
103
|
+
&& (typeof role.description !== 'string' || role.description.length > 500)) {
|
|
104
|
+
errors.push(`role ${indexArg + 1} description must contain at most 500 characters`);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
return errors;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export const validateHostedAppPlatformOidcClaims = (
|
|
111
|
+
claimsArg: unknown,
|
|
112
|
+
expectedArg: {
|
|
113
|
+
issuer: string;
|
|
114
|
+
appInstanceId: string;
|
|
115
|
+
nonce?: string;
|
|
116
|
+
nowEpochSeconds?: number;
|
|
117
|
+
},
|
|
118
|
+
): string[] => {
|
|
119
|
+
if (!claimsArg || typeof claimsArg !== 'object' || Array.isArray(claimsArg)) {
|
|
120
|
+
return ['OIDC claims must be an object'];
|
|
121
|
+
}
|
|
122
|
+
const claims = claimsArg as Record<string, unknown>;
|
|
123
|
+
const errors: string[] = [];
|
|
124
|
+
if (claims.iss !== expectedArg.issuer) errors.push('OIDC issuer does not match');
|
|
125
|
+
if (claims.aud !== expectedArg.appInstanceId) errors.push('OIDC audience does not match');
|
|
126
|
+
if (claims[hostedAppOidcAppInstanceIdClaim] !== expectedArg.appInstanceId) {
|
|
127
|
+
errors.push('OIDC app instance does not match the audience');
|
|
128
|
+
}
|
|
129
|
+
if (typeof claims.sub !== 'string' || claims.sub.length === 0) {
|
|
130
|
+
errors.push('OIDC subject is missing or malformed');
|
|
131
|
+
}
|
|
132
|
+
if (typeof claims.preferred_username !== 'string'
|
|
133
|
+
|| claims.preferred_username.trim().length === 0) {
|
|
134
|
+
errors.push('OIDC preferred username is missing or malformed');
|
|
135
|
+
}
|
|
136
|
+
const now = expectedArg.nowEpochSeconds ?? Math.floor(Date.now() / 1000);
|
|
137
|
+
if (!Number.isSafeInteger(claims.iat) || (claims.iat as number) < 0) {
|
|
138
|
+
errors.push('OIDC issued-at time is missing or malformed');
|
|
139
|
+
}
|
|
140
|
+
if (!Number.isSafeInteger(claims.exp) || (claims.exp as number) <= now) {
|
|
141
|
+
errors.push('OIDC token is expired or has malformed expiry');
|
|
142
|
+
}
|
|
143
|
+
if (!Number.isSafeInteger(claims.auth_time)
|
|
144
|
+
|| (claims.auth_time as number) < 0
|
|
145
|
+
|| (claims.auth_time as number) > now) {
|
|
146
|
+
errors.push('OIDC authentication time is missing or malformed');
|
|
147
|
+
}
|
|
148
|
+
if (expectedArg.nonce !== undefined && claims.nonce !== expectedArg.nonce) {
|
|
149
|
+
errors.push('OIDC nonce does not match');
|
|
150
|
+
}
|
|
151
|
+
const roles = claims[hostedAppOidcRoleClaim];
|
|
152
|
+
if (!Array.isArray(roles) || roles.length < 1 || roles.length > 32) {
|
|
153
|
+
errors.push('OIDC roles must be an array with between 1 and 32 entries');
|
|
154
|
+
} else if (roles.some((roleArg) => typeof roleArg !== 'string'
|
|
155
|
+
|| !hostedAppRoleIdRegex.test(roleArg))
|
|
156
|
+
|| new Set(roles).size !== roles.length) {
|
|
157
|
+
errors.push('OIDC roles contain malformed or duplicate identifiers');
|
|
158
|
+
}
|
|
159
|
+
return errors;
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
export const validateHostedAppPlatformOidcRegistration = (
|
|
163
|
+
registrationArg: unknown,
|
|
164
|
+
expectedArg: { appOrigin: string },
|
|
165
|
+
): string[] => {
|
|
166
|
+
if (!registrationArg || typeof registrationArg !== 'object'
|
|
167
|
+
|| Array.isArray(registrationArg)) {
|
|
168
|
+
return ['OIDC registration must be an object'];
|
|
169
|
+
}
|
|
170
|
+
const registration = registrationArg as Record<string, unknown>;
|
|
171
|
+
const errors: string[] = [];
|
|
172
|
+
let expectedOrigin: string | undefined;
|
|
173
|
+
try {
|
|
174
|
+
const parsedAppOrigin = new URL(expectedArg.appOrigin);
|
|
175
|
+
if (parsedAppOrigin.protocol !== 'https:'
|
|
176
|
+
|| parsedAppOrigin.username
|
|
177
|
+
|| parsedAppOrigin.password
|
|
178
|
+
|| parsedAppOrigin.origin !== expectedArg.appOrigin) {
|
|
179
|
+
errors.push('Expected OIDC app origin must be a canonical credential-free HTTPS origin');
|
|
180
|
+
} else {
|
|
181
|
+
expectedOrigin = parsedAppOrigin.origin;
|
|
182
|
+
}
|
|
183
|
+
} catch {
|
|
184
|
+
errors.push('Expected OIDC app origin must be an absolute URL origin');
|
|
185
|
+
}
|
|
186
|
+
if (typeof registration.appInstanceId !== 'string'
|
|
187
|
+
|| !hostedAppOpaqueIdRegex.test(registration.appInstanceId)) {
|
|
188
|
+
errors.push('OIDC registration appInstanceId is missing or malformed');
|
|
189
|
+
}
|
|
190
|
+
const statuses = ['disabled', 'enabling', 'enabled', 'disabling', 'error'];
|
|
191
|
+
if (typeof registration.status !== 'string' || !statuses.includes(registration.status)) {
|
|
192
|
+
errors.push('OIDC registration status is unsupported');
|
|
193
|
+
}
|
|
194
|
+
errors.push(...validateHostedAppRoleDefinitions(registration.roleDefinitions)
|
|
195
|
+
.map((errorArg) => `OIDC registration ${errorArg}`));
|
|
196
|
+
if (!Number.isSafeInteger(registration.updatedAt) || (registration.updatedAt as number) < 0) {
|
|
197
|
+
errors.push('OIDC registration updatedAt is missing or malformed');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const redirectUris = registration.redirectUris;
|
|
201
|
+
if (!Array.isArray(redirectUris)
|
|
202
|
+
|| redirectUris.length > 8
|
|
203
|
+
|| redirectUris.some((uriArg) => typeof uriArg !== 'string')) {
|
|
204
|
+
errors.push('OIDC registration redirectUris are malformed');
|
|
205
|
+
} else {
|
|
206
|
+
if (registration.status === 'disabled' && redirectUris.length !== 0) {
|
|
207
|
+
errors.push('Disabled OIDC registration must not retain redirect URIs');
|
|
208
|
+
}
|
|
209
|
+
if (registration.status !== 'disabled'
|
|
210
|
+
&& registration.status !== 'error'
|
|
211
|
+
&& redirectUris.length < 1) {
|
|
212
|
+
errors.push('Active OIDC registration requires a redirect URI');
|
|
213
|
+
}
|
|
214
|
+
if (new Set(redirectUris).size !== redirectUris.length) {
|
|
215
|
+
errors.push('OIDC registration redirect URIs must be unique');
|
|
216
|
+
}
|
|
217
|
+
for (const redirectUri of redirectUris) {
|
|
218
|
+
try {
|
|
219
|
+
const parsed = new URL(redirectUri);
|
|
220
|
+
if (parsed.protocol !== 'https:'
|
|
221
|
+
|| parsed.username
|
|
222
|
+
|| parsed.password
|
|
223
|
+
|| parsed.search
|
|
224
|
+
|| parsed.hash
|
|
225
|
+
|| parsed.toString() !== redirectUri) {
|
|
226
|
+
errors.push('OIDC registration redirect URIs must be canonical credential-free HTTPS URLs without query or fragment');
|
|
227
|
+
}
|
|
228
|
+
if (expectedOrigin && parsed.origin !== expectedOrigin) {
|
|
229
|
+
errors.push('OIDC registration redirect URIs must use the app origin');
|
|
230
|
+
}
|
|
231
|
+
} catch {
|
|
232
|
+
errors.push('OIDC registration redirect URIs must be absolute URLs');
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const requiresIssuer = registration.status === 'enabling'
|
|
238
|
+
|| registration.status === 'enabled'
|
|
239
|
+
|| registration.status === 'disabling';
|
|
240
|
+
if (requiresIssuer || registration.issuer !== undefined) {
|
|
241
|
+
try {
|
|
242
|
+
const issuer = new URL(registration.issuer as string);
|
|
243
|
+
if (issuer.protocol !== 'https:' || issuer.username || issuer.password
|
|
244
|
+
|| issuer.search || issuer.hash) {
|
|
245
|
+
errors.push('OIDC registration issuer must be a credential-free HTTPS URL without query or fragment');
|
|
246
|
+
}
|
|
247
|
+
} catch {
|
|
248
|
+
errors.push('OIDC registration issuer must be an absolute URL');
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const requiresClientId = registration.status === 'enabling'
|
|
252
|
+
|| registration.status === 'enabled'
|
|
253
|
+
|| registration.status === 'disabling';
|
|
254
|
+
if (registration.status === 'disabled'
|
|
255
|
+
&& (registration.issuer !== undefined || registration.clientId !== undefined)) {
|
|
256
|
+
errors.push('Disabled OIDC registration must not retain issuer or client metadata');
|
|
257
|
+
}
|
|
258
|
+
if (requiresClientId && registration.clientId !== registration.appInstanceId) {
|
|
259
|
+
errors.push('OIDC registration clientId must equal appInstanceId');
|
|
260
|
+
} else if (registration.clientId !== undefined
|
|
261
|
+
&& registration.clientId !== registration.appInstanceId) {
|
|
262
|
+
errors.push('OIDC registration clientId must equal appInstanceId when present');
|
|
263
|
+
}
|
|
264
|
+
if (registration.status === 'error'
|
|
265
|
+
&& (typeof registration.error !== 'string' || registration.error.length < 1)) {
|
|
266
|
+
errors.push('Errored OIDC registration requires an error message');
|
|
267
|
+
}
|
|
268
|
+
return errors;
|
|
269
|
+
};
|
|
270
|
+
|
|
3
271
|
export type THostedAppRuntimeStatus =
|
|
4
272
|
| 'starting'
|
|
5
273
|
| 'running'
|
|
@@ -54,6 +54,8 @@ export type TImmutableImageRolloutStatus =
|
|
|
54
54
|
|
|
55
55
|
export interface ICoreflowRuntimeCapabilities {
|
|
56
56
|
immutableImageDeploymentVersion: 1;
|
|
57
|
+
/** Coreflow can answer the versioned, node-scoped Corestore inventory probe. */
|
|
58
|
+
corestoreInventoryVersion?: 1;
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
/**
|
package/ts/requests/corestore.ts
CHANGED
|
@@ -26,11 +26,63 @@ export interface ICorestoreServiceResources {
|
|
|
26
26
|
export interface ICorestoreNodeInventory {
|
|
27
27
|
/** Swarm node hostnames of the reporting coreflow. */
|
|
28
28
|
nodeNames: string[];
|
|
29
|
+
protocolVersion: 1;
|
|
30
|
+
checkedAt: number;
|
|
29
31
|
reachable: boolean;
|
|
32
|
+
errorCode?: 'NODE_DISCOVERY_FAILED' | 'CORESTORE_UNREACHABLE';
|
|
30
33
|
error?: string;
|
|
31
34
|
services: ICorestoreServiceResources[];
|
|
32
35
|
}
|
|
33
36
|
|
|
37
|
+
export type TCorestoreInventoryProbeStatus =
|
|
38
|
+
| 'ok'
|
|
39
|
+
| 'connection-missing'
|
|
40
|
+
| 'connection-inspection-failed'
|
|
41
|
+
| 'identity-unverified'
|
|
42
|
+
| 'node-tag-missing'
|
|
43
|
+
| 'connection-ambiguous'
|
|
44
|
+
| 'handler-unsupported'
|
|
45
|
+
| 'rpc-timeout'
|
|
46
|
+
| 'rpc-rejected'
|
|
47
|
+
| 'rpc-invalid-response'
|
|
48
|
+
| 'node-identity-mismatch'
|
|
49
|
+
| 'corestore-unreachable';
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Cloudly's control-plane view of one expected node. Every expected online
|
|
53
|
+
* node receives exactly one probe result, including transport and registration
|
|
54
|
+
* failures that used to disappear from the inventory array.
|
|
55
|
+
*/
|
|
56
|
+
export interface ICorestoreInventoryProbe {
|
|
57
|
+
expectedNodeName: string;
|
|
58
|
+
expectedClusterId?: string;
|
|
59
|
+
processRunning?: boolean;
|
|
60
|
+
cloudlyRegistered: boolean;
|
|
61
|
+
inventoryRpcReady: boolean;
|
|
62
|
+
status: TCorestoreInventoryProbeStatus;
|
|
63
|
+
connectionId?: string;
|
|
64
|
+
reporterSessionId?: string;
|
|
65
|
+
capabilityVersion?: number;
|
|
66
|
+
observedNodeNames: string[];
|
|
67
|
+
checkedAt: number;
|
|
68
|
+
lastSuccessfulInventoryAt?: number;
|
|
69
|
+
message?: string;
|
|
70
|
+
inventory?: ICorestoreNodeInventory;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface ICorestoreInventoryReport {
|
|
74
|
+
checkedAt: number;
|
|
75
|
+
inventories: ICorestoreNodeInventory[];
|
|
76
|
+
probes: ICorestoreInventoryProbe[];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Final registration tag restored only after identity and capability tags. */
|
|
80
|
+
export interface ICoreflowInventoryRegistration {
|
|
81
|
+
registrationVersion: 1;
|
|
82
|
+
reporterSessionId: string;
|
|
83
|
+
registeredAt: number;
|
|
84
|
+
}
|
|
85
|
+
|
|
34
86
|
export interface IReq_Any_Cloudly_GetCorestoreInventory
|
|
35
87
|
extends plugins.typedrequestInterfaces.implementsTR<
|
|
36
88
|
plugins.typedrequestInterfaces.ITypedRequest,
|
|
@@ -40,9 +92,7 @@ extends plugins.typedrequestInterfaces.implementsTR<
|
|
|
40
92
|
request: {
|
|
41
93
|
identity: IIdentity;
|
|
42
94
|
};
|
|
43
|
-
response:
|
|
44
|
-
inventories: ICorestoreNodeInventory[];
|
|
45
|
-
};
|
|
95
|
+
response: ICorestoreInventoryReport;
|
|
46
96
|
}
|
|
47
97
|
|
|
48
98
|
export interface IReq_Cloudly_Coreflow_GetCorestoreInventory
|