@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 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: '18.0.0',
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
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9hcHBzdG9yZS90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFpQ0EsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUc7SUFDdkMsVUFBVSxFQUFFLHFCQUFxQjtJQUNqQyxZQUFZLEVBQUUsdUJBQXVCO0lBQ3JDLGVBQWUsRUFBRSwyQkFBMkI7SUFDNUMseUJBQXlCLEVBQUUsdUNBQXVDO0NBQzFELENBQUMifQ==
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9hcHBzdG9yZS90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQ0wsZ0NBQWdDLEdBRWpDLE1BQU0sc0JBQXNCLENBQUM7QUFpQzlCLE1BQU0sQ0FBQyxNQUFNLHlCQUF5QixHQUFHO0lBQ3ZDLFVBQVUsRUFBRSxxQkFBcUI7SUFDakMsWUFBWSxFQUFFLHVCQUF1QjtJQUNyQyxlQUFlLEVBQUUsMkJBQTJCO0lBQzVDLHlCQUF5QixFQUFFLHVDQUF1QztDQUMxRCxDQUFDO0FBK0pYLE1BQU0sbUJBQW1CLEdBQUcsb0JBQW9CLENBQUM7QUFFakQsTUFBTSxDQUFDLE1BQU0sc0NBQXNDLEdBQUcsQ0FDcEQsYUFBc0IsRUFDWixFQUFFO0lBQ1osSUFBSSxhQUFhLEtBQUssU0FBUztRQUFFLE9BQU8sRUFBRSxDQUFDO0lBQzNDLElBQUksQ0FBQyxhQUFhLElBQUksT0FBTyxhQUFhLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztRQUN4RixPQUFPLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBQ0QsTUFBTSxVQUFVLEdBQUcsYUFBd0MsQ0FBQztJQUM1RCxNQUFNLE1BQU0sR0FBYSxFQUFFLENBQUM7SUFDNUIsSUFBSSxPQUFPLFVBQVUsQ0FBQyxZQUFZLEtBQUssUUFBUTtXQUMxQyxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQztXQUN4QyxVQUFVLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUM7V0FDeEMsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDO1dBQ3hDLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQztXQUNwQyxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsWUFBWSxFQUFFLHFC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
@@ -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
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG9zdGVkYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvZGF0YS9ob3N0ZWRhcHAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serve.zone/interfaces",
3
- "version": "18.0.0",
3
+ "version": "19.0.0",
4
4
  "private": false,
5
5
  "description": "Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.",
6
6
  "exports": {
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.
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/interfaces',
6
- version: '18.0.0',
6
+ version: '19.0.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.'
8
8
  }
@@ -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;
@@ -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
  /**
@@ -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