@inquir/compute 0.4.2 → 0.4.5

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.
Files changed (42) hide show
  1. package/README.md +60 -1
  2. package/dist/apps.d.ts +270 -12
  3. package/dist/apps.d.ts.map +1 -1
  4. package/dist/apps.js +30 -2
  5. package/dist/apps.js.map +1 -1
  6. package/dist/compose.d.ts +51 -0
  7. package/dist/compose.d.ts.map +1 -0
  8. package/dist/compose.js +13 -0
  9. package/dist/compose.js.map +1 -0
  10. package/dist/discovery.d.ts.map +1 -1
  11. package/dist/discovery.js +2 -8
  12. package/dist/discovery.js.map +1 -1
  13. package/dist/index.d.ts +4 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +4 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/local-runner.d.ts.map +1 -1
  18. package/dist/local-runner.js +2 -8
  19. package/dist/local-runner.js.map +1 -1
  20. package/dist/replica-roles.d.ts +51 -0
  21. package/dist/replica-roles.d.ts.map +1 -0
  22. package/dist/replica-roles.js +8 -0
  23. package/dist/replica-roles.js.map +1 -0
  24. package/dist/sandboxes.d.ts +434 -0
  25. package/dist/sandboxes.d.ts.map +1 -0
  26. package/dist/sandboxes.js +359 -0
  27. package/dist/sandboxes.js.map +1 -0
  28. package/dist/system-packages.d.ts +2592 -0
  29. package/dist/system-packages.d.ts.map +1 -0
  30. package/dist/system-packages.js +605 -0
  31. package/dist/system-packages.js.map +1 -0
  32. package/dist/transport.d.ts +43 -5
  33. package/dist/transport.d.ts.map +1 -1
  34. package/dist/transport.js +13 -1
  35. package/dist/transport.js.map +1 -1
  36. package/dist/tsx-loader.d.ts +9 -0
  37. package/dist/tsx-loader.d.ts.map +1 -0
  38. package/dist/tsx-loader.js +26 -0
  39. package/dist/tsx-loader.js.map +1 -0
  40. package/dist/types.d.ts +13 -0
  41. package/dist/types.d.ts.map +1 -1
  42. package/package.json +7 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-packages.d.ts","sourceRoot":"","sources":["../src/system-packages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,605 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * System packages (OS packages such as ffmpeg) are declared in inquir.yaml —
4
+ * the one config format for every language — and applied by a deploy:
5
+ *
6
+ * build:
7
+ * system:
8
+ * presets: [ffmpeg]
9
+ * packages: [poppler-utils, chromium]
10
+ * functions:
11
+ * transcode: # per-function override; replaces the default (no merge)
12
+ * build:
13
+ * system:
14
+ * presets: [ffmpeg]
15
+ *
16
+ * This module only reads and validates that schema (INQUIR_YAML_JSON_SCHEMA
17
+ * is what editors use for completion); it is never a second config source.
18
+ * The platform is the authority: GET /functions/system-presets lists its
19
+ * catalog, and the deploy validates the block again.
20
+ */
21
+ /** Presets of catalog v1 (Debian bookworm). */
22
+ export const SYSTEM_PRESET_NAMES = [
23
+ 'ffmpeg', 'fonts', 'ghostscript', 'imagemagick', 'libvips', 'poppler', 'tesseract',
24
+ ];
25
+ /** tesseract `langs` values (tesseract-ocr-<lang> packages in bookworm). */
26
+ export const TESSERACT_LANGS = [
27
+ 'ara', 'bul', 'ces', 'chi-sim', 'chi-tra', 'dan', 'deu', 'ell', 'eng', 'est', 'fin', 'fra', 'heb', 'hin', 'hrv',
28
+ 'hun', 'ind', 'ita', 'jpn', 'kat', 'kaz', 'kor', 'lav', 'lit', 'nld', 'nor', 'pol', 'por', 'ron', 'rus', 'slk',
29
+ 'slv', 'spa', 'srp', 'swe', 'tha', 'tur', 'ukr', 'vie',
30
+ ];
31
+ /** Debian package name with an optional apt `=version` pin (the platform applies the same rule). */
32
+ export const SYSTEM_PACKAGE_NAME_PATTERN = '^(?!.*\\.\\.)[a-z0-9](?:[a-z0-9+.-]{0,61}[a-z0-9])?(=[A-Za-z0-9.+~:_-]{1,64})?$';
33
+ /** The free-form package cap the platform applies by default (the Free plan figure). */
34
+ export const SYSTEM_MAX_PACKAGES = 10;
35
+ /** At most this many presets per block. */
36
+ export const SYSTEM_MAX_PRESETS = 8;
37
+ /** Presets that take options (an object entry); every other preset is a plain name. */
38
+ export const SYSTEM_PRESETS_WITH_OPTIONS = ['tesseract'];
39
+ /**
40
+ * Package names a function image refuses (daemons, privilege tools, kernels,
41
+ * package tooling); an optional `=version` pin does not change that. The
42
+ * platform's validator uses the same list (a test keeps them in step).
43
+ */
44
+ export const SYSTEM_PACKAGE_DENYLIST_PATTERN = '^(systemd.*|init|sudo|sudo-ldap|doas|openssh-server|docker.*|containerd.*|podman.*|runc|crun|linux-image-.*|linux-headers-.*|.*-dkms|apt-transport-.*|apt|dpkg|cron|anacron|rsyslog|udev|dbus)(=.*)?$';
45
+ const packageNameRegex = new RegExp(SYSTEM_PACKAGE_NAME_PATTERN);
46
+ const denylistRegex = new RegExp(SYSTEM_PACKAGE_DENYLIST_PATTERN);
47
+ const unique = (values) => new Set(values.map((value) => JSON.stringify(value))).size === values.length;
48
+ const presetRefSchema = z.union([
49
+ z.enum(SYSTEM_PRESET_NAMES.filter((name) => !SYSTEM_PRESETS_WITH_OPTIONS.includes(name))),
50
+ z.literal('tesseract'),
51
+ z.object({ name: z.literal('tesseract'), langs: z.array(z.enum(TESSERACT_LANGS)).max(8).refine(unique, 'languages must be unique').nullable().optional() }).strict(),
52
+ ]);
53
+ /** zod twin of INQUIR_YAML_JSON_SCHEMA's system block. */
54
+ export const functionSystemConfigSchema = z.object({
55
+ presets: z.array(presetRefSchema).max(SYSTEM_MAX_PRESETS).refine(unique, 'presets must be unique').nullable().optional(),
56
+ packages: z.array(z.string()
57
+ .regex(packageNameRegex, 'Debian package name (optional =version)')
58
+ .refine((name) => !denylistRegex.test(name), 'this package is not allowed in a function image'))
59
+ .max(SYSTEM_MAX_PACKAGES).refine(unique, 'packages must be unique').nullable().optional(),
60
+ }).strict().nullable();
61
+ /**
62
+ * `build.dependencies`: language packages, the same key for every runtime
63
+ * (node `name@version`, python a pip requirement such as `name==version`, go
64
+ * `module@version`). Only the shape is checked here; the platform validates
65
+ * each entry by the function's runtime and merges the list into its build
66
+ * workspace's package.json / requirements.txt / go.mod
67
+ * (docs/FUNCTION_BUILD_DEPENDENCIES.md; FUNCTIONS_INQUIR_YAML_DEPENDENCIES).
68
+ */
69
+ export const buildDependenciesSchema = z.array(z.string().min(1).max(512)).max(200).nullable();
70
+ const buildSchema = z.object({
71
+ system: functionSystemConfigSchema.optional(),
72
+ dependencies: buildDependenciesSchema.optional(),
73
+ }).strict().nullable();
74
+ /** The parts of an inquir.yaml document the functions read; apps' `version` and `services` are checked by the platform. */
75
+ export const inquirYamlFunctionsSchema = z.object({
76
+ version: z.unknown().optional(),
77
+ services: z.unknown().optional(),
78
+ build: buildSchema.optional(),
79
+ functions: z.record(z.string().min(1), z.object({ build: buildSchema.optional() }).strict().nullable()).nullable().optional(),
80
+ }).strict();
81
+ /**
82
+ * The system block one inquir.yaml document declares for `functionName`:
83
+ * functions.<name>.build.system first, then build.system; undefined when it
84
+ * declares neither (null: declared as none). Throws a ZodError on a malformed
85
+ * document. The platform resolves a deploy the same way, the function's own
86
+ * inquir.yaml before the project's.
87
+ */
88
+ export function declaredSystemConfig(document, functionName) {
89
+ if (document === null || document === undefined)
90
+ return undefined;
91
+ const parsed = inquirYamlFunctionsSchema.parse(document);
92
+ const own = parsed.functions?.[functionName]?.build?.system;
93
+ const declared = own !== undefined ? own : parsed.build?.system;
94
+ if (!declared)
95
+ return declared;
96
+ return { presets: declared.presets ?? [], packages: declared.packages ?? [] };
97
+ }
98
+ const presetItemSchema = {
99
+ anyOf: [
100
+ { enum: [...SYSTEM_PRESET_NAMES], description: 'A platform preset (Debian bookworm packages plus env)' },
101
+ {
102
+ type: 'object',
103
+ required: ['name'],
104
+ additionalProperties: false,
105
+ description: 'A preset with options (tesseract only)',
106
+ properties: {
107
+ name: { enum: [...SYSTEM_PRESETS_WITH_OPTIONS] },
108
+ langs: { type: ['array', 'null'], maxItems: 8, uniqueItems: true, items: { enum: [...TESSERACT_LANGS] }, description: 'Extra OCR languages' },
109
+ },
110
+ },
111
+ ],
112
+ };
113
+ /** The keys inquir.yaml may hold at the top level (apps: version, services; functions: build, functions). */
114
+ export const INQUIR_YAML_TOP_LEVEL_KEYS = ['version', 'services', 'build', 'functions'];
115
+ /**
116
+ * `services.web.scale` (docs/roadmap/STATEFUL_REPLICAS.md §7): the platform's
117
+ * validator is src/apps/app-scale-spec.ts; these constants and the schema
118
+ * below are its twin, kept equal by src/services/inquir-yaml-schema-parity.test.ts.
119
+ * Cross-field rules JSON Schema cannot express (an ordinal below `replicas`,
120
+ * a `fallback` or `public` that names an existing endpoint) are the platform's.
121
+ */
122
+ export const SCALE_MAX_REPLICAS = 8;
123
+ export const SCALE_MAX_ENDPOINTS = 8;
124
+ export const SCALE_NAME_PATTERN = '^[a-z][a-z0-9-]{0,30}$';
125
+ export const SCALE_ORDINAL_SELECTOR_PATTERN = '^[0-9]{1,2}(-([0-9]{1,2})?)?(,[0-9]{1,2}(-([0-9]{1,2})?)?)*$';
126
+ export const SCALE_ORDINAL_KEY_PATTERN = '^(0|[1-9][0-9]?)$';
127
+ const scaleName = { type: 'string', pattern: SCALE_NAME_PATTERN };
128
+ const scaleInt = (minimum, maximum) => ({ type: 'integer', minimum, ...(maximum === undefined ? {} : { maximum }) });
129
+ /** A failover command (rank, promote, rejoin): run in the replica's container, bounded by timeoutSeconds. */
130
+ const scaleCommand = {
131
+ type: 'object', additionalProperties: false, required: ['command'],
132
+ properties: {
133
+ command: { type: 'array', minItems: 1, maxItems: 32, items: { type: 'string', minLength: 1, maxLength: 2048 } },
134
+ timeoutSeconds: { type: 'integer', minimum: 1, maximum: 3600 },
135
+ },
136
+ };
137
+ export const SCALE_JSON_SCHEMA = {
138
+ description: 'Alpha: stateful replicas may still change and have limits; keep backups of the data they hold. Replica intent: stateless (identical replicas) or stateful (ordered replicas 0..N-1, each with its own volumes, private name and address). Where stateful replicas are not enabled for the workspace, a deploy that declares it is refused. Keys declared here are managed by this file: other surfaces change them only with an explicit override.',
139
+ type: 'object',
140
+ additionalProperties: false,
141
+ properties: {
142
+ mode: { enum: ['stateless', 'stateful'] },
143
+ replicas: scaleInt(1, SCALE_MAX_REPLICAS),
144
+ podManagement: { enum: ['ordered', 'parallel'] },
145
+ update: {
146
+ type: 'object', additionalProperties: false,
147
+ properties: {
148
+ order: { enum: ['reverse', 'forward'] },
149
+ partition: scaleInt(0, SCALE_MAX_REPLICAS),
150
+ maxUnavailable: scaleInt(1, SCALE_MAX_REPLICAS),
151
+ minReadySeconds: scaleInt(0, 3600),
152
+ progressDeadlineSeconds: scaleInt(30, 86400),
153
+ },
154
+ },
155
+ placement: {
156
+ type: 'object', additionalProperties: false,
157
+ properties: { spread: { enum: ['host', 'location'] }, allowSameHost: { type: 'boolean' } },
158
+ },
159
+ hostLoss: { enum: ['wait', 'rebuild'] },
160
+ hostLossGraceSeconds: scaleInt(60, 86400),
161
+ retention: {
162
+ type: 'object', additionalProperties: false,
163
+ properties: {
164
+ whenScaledDown: { enum: ['retain', 'delete'] },
165
+ whenDeleted: { enum: ['retain', 'delete'] },
166
+ retentionDays: scaleInt(1, 90),
167
+ },
168
+ },
169
+ endpoints: {
170
+ type: 'object',
171
+ maxProperties: SCALE_MAX_ENDPOINTS,
172
+ propertyNames: { pattern: SCALE_NAME_PATTERN, not: { const: 'default' } },
173
+ additionalProperties: {
174
+ type: 'object', additionalProperties: false,
175
+ oneOf: [{ required: ['role'] }, { required: ['ordinals'] }],
176
+ // A single-writer endpoint never falls back to other replicas: with no writer it has no backend.
177
+ if: { required: ['max'] },
178
+ then: { not: { required: ['fallback'] } },
179
+ properties: {
180
+ role: scaleName,
181
+ ordinals: { type: 'string', pattern: SCALE_ORDINAL_SELECTOR_PATTERN },
182
+ max: { const: 1 },
183
+ fallback: scaleName,
184
+ },
185
+ },
186
+ },
187
+ public: scaleName,
188
+ backup: {
189
+ oneOf: [
190
+ { type: 'object', additionalProperties: false, required: ['from'], properties: { from: { enum: ['all', 'none'] } } },
191
+ { type: 'object', additionalProperties: false, required: ['ordinals'],
192
+ properties: { ordinals: { type: 'array', minItems: 1, maxItems: SCALE_MAX_REPLICAS, items: scaleInt(0, SCALE_MAX_REPLICAS - 1) } } },
193
+ { type: 'object', additionalProperties: false, required: ['role'], properties: { role: scaleName, fallback: { type: 'boolean' } } },
194
+ ],
195
+ },
196
+ failover: {
197
+ type: 'object', additionalProperties: false, required: ['enabled'],
198
+ properties: {
199
+ enabled: { type: 'boolean' },
200
+ leaderRole: scaleName,
201
+ replicaRole: scaleName,
202
+ leaseTtlSeconds: scaleInt(5, 300),
203
+ detectAfterSeconds: scaleInt(5, 3600),
204
+ rank: scaleCommand,
205
+ maxRankLag: scaleInt(0),
206
+ promote: scaleCommand,
207
+ rejoin: scaleCommand,
208
+ isolation: { enum: ['failsafe', 'fence'] },
209
+ switchoverOnUpdate: { type: 'boolean' },
210
+ },
211
+ if: { properties: { enabled: { const: true } } },
212
+ then: { required: ['leaderRole', 'rank', 'promote'] },
213
+ },
214
+ ordinals: {
215
+ type: 'object',
216
+ propertyNames: { pattern: SCALE_ORDINAL_KEY_PATTERN },
217
+ additionalProperties: {
218
+ type: 'object', additionalProperties: false,
219
+ properties: {
220
+ resources: {
221
+ type: 'object', additionalProperties: false,
222
+ properties: {
223
+ cpuVCpus: { type: 'number', minimum: 0.05, maximum: 16 },
224
+ memoryMb: scaleInt(64, 8192),
225
+ },
226
+ },
227
+ env: {
228
+ type: 'object', maxProperties: 64,
229
+ propertyNames: { pattern: '^[A-Za-z_][A-Za-z0-9_]*$', maxLength: 256 },
230
+ additionalProperties: { type: 'string', maxLength: 32768 },
231
+ },
232
+ hostLoss: { enum: ['wait', 'rebuild'] },
233
+ },
234
+ },
235
+ },
236
+ },
237
+ // Only mode and replicas mean anything for identical (stateless) replicas.
238
+ if: { not: { required: ['mode'], properties: { mode: { const: 'stateful' } } } },
239
+ then: { propertyNames: { enum: ['mode', 'replicas'] } },
240
+ };
241
+ /**
242
+ * services.web.runtime.roles (stateful replicas, role endpoints): what each
243
+ * replica is, for scale.endpoints. Exactly one form: a probe the runner runs
244
+ * (an HTTP GET or a command whose answer is the role), or roles by ordinal.
245
+ * The platform's validator is src/apps/stateful-replicas/role-spec.ts.
246
+ */
247
+ const ROLE_NAME_JSON_SCHEMA = { type: 'string', pattern: SCALE_NAME_PATTERN, not: { const: 'unknown' } };
248
+ /**
249
+ * `services.web.runtime.hooks` (docs/roadmap/STATEFUL_REPLICAS.md §3.11): the
250
+ * init hook of a stateful application's replicas. The platform's validator is
251
+ * src/apps/stateful-replicas/init-hook.ts (runtimeHooksSchema).
252
+ */
253
+ const HOOKS_JSON_SCHEMA = {
254
+ description: 'Commands run in each replica container itself. init: before its command, always or while a declared writable ' +
255
+ 'volume is empty and was never bootstrapped (a replica bootstraps its data from another). Stateful applications only. ' +
256
+ 'Frozen with each release.',
257
+ type: 'object',
258
+ additionalProperties: false,
259
+ properties: {
260
+ init: {
261
+ type: 'object',
262
+ additionalProperties: false,
263
+ required: ['command'],
264
+ properties: {
265
+ command: { type: 'array', minItems: 1, maxItems: 32, items: { type: 'string', minLength: 1, maxLength: 2048 } },
266
+ when: { enum: ['always', 'emptyVolume'], description: 'always (default), or emptyVolume' },
267
+ timeoutSeconds: { type: 'integer', minimum: 1, maximum: 3600, description: 'Default 600; the start fails past it' },
268
+ },
269
+ },
270
+ },
271
+ };
272
+ const ROLES_JSON_SCHEMA = {
273
+ description: 'What each replica of a stateful application is, for its role endpoints (scale.endpoints): a probe the runner runs ' +
274
+ '(an HTTP path or a command whose answer is the role), or roles by ordinal. Frozen with each release.',
275
+ type: 'object',
276
+ additionalProperties: false,
277
+ properties: {
278
+ probe: {
279
+ type: 'object',
280
+ additionalProperties: false,
281
+ oneOf: [{ required: ['http'] }, { required: ['command'] }],
282
+ properties: {
283
+ http: {
284
+ type: 'object',
285
+ additionalProperties: false,
286
+ required: ['path'],
287
+ properties: {
288
+ path: { type: 'string', minLength: 1, maxLength: 512, pattern: '^/' },
289
+ port: { type: 'string', minLength: 1, maxLength: 32, description: 'A runtime.ports name; the primary port by default' },
290
+ },
291
+ },
292
+ command: { type: 'array', minItems: 1, maxItems: 32, items: { type: 'string', minLength: 1, maxLength: 2048 } },
293
+ intervalSeconds: { type: 'integer', minimum: 1, maximum: 60 },
294
+ timeoutSeconds: { type: 'integer', minimum: 1, maximum: 30 },
295
+ successThreshold: { type: 'integer', minimum: 1, maximum: 10 },
296
+ },
297
+ },
298
+ byOrdinal: {
299
+ type: 'object',
300
+ propertyNames: { pattern: SCALE_ORDINAL_KEY_PATTERN },
301
+ additionalProperties: ROLE_NAME_JSON_SCHEMA,
302
+ },
303
+ default: ROLE_NAME_JSON_SCHEMA,
304
+ },
305
+ oneOf: [
306
+ { required: ['probe'], not: { anyOf: [{ required: ['byOrdinal'] }, { required: ['default'] }] } },
307
+ { not: { required: ['probe'] }, anyOf: [{ required: ['byOrdinal'] }, { required: ['default'] }] },
308
+ ],
309
+ };
310
+ /**
311
+ * The application settings inquir.yaml `services.web` declares with the apps
312
+ * API's own shapes (docs/roadmap/INQUIR_COMPOSE.md §3.6.2). The platform's
313
+ * validators are src/apps/app-settings-schema.ts; these bounds are their twin,
314
+ * kept equal by src/services/inquir-yaml-schema-parity.test.ts.
315
+ */
316
+ export const APP_SCALING_MAX_REPLICAS = 8;
317
+ export const APP_SCALING_MAX_DELAY_SECONDS = 30 * 24 * 60 * 60;
318
+ export const APP_AUTOSCALING_MAX_STABILIZATION_SECONDS = 3600;
319
+ export const APP_AUTOSCALING_CPU_PERCENT_RANGE = [10, 100];
320
+ export const APP_AUTOSCALING_MAX_CONCURRENCY = 10_000;
321
+ export const APP_ROLLOUT_MAX_FIGURE = 8;
322
+ export const APP_ROLLOUT_PROGRESS_DEADLINE_RANGE = [30, 3600];
323
+ /** A registry image pinned by digest: the only kind a worker runner pulls. */
324
+ export const PINNED_IMAGE_REF_PATTERN = '^[A-Za-z0-9][A-Za-z0-9._:/-]*@sha256:[a-f0-9]{64}$';
325
+ const nullableInt = (minimum, maximum) => ({ type: ['integer', 'null'], minimum, maximum });
326
+ const NETWORK_POLICY_JSON_SCHEMA = {
327
+ description: 'Network policy, the same object as the apps API: ingress private (default for a new application) or public ' +
328
+ '(a generated public domain), egress full (default) or none. A missing field keeps the current value. Keys declared ' +
329
+ 'here are managed by this file: a change elsewhere is kept until the next deploy, which restores the file\'s value.',
330
+ type: 'object',
331
+ additionalProperties: false,
332
+ properties: {
333
+ ingress: { enum: ['private', 'public'] },
334
+ egress: { enum: ['none', 'full'] },
335
+ allow: { type: 'array', maxItems: 64, items: { type: 'string', minLength: 1, maxLength: 253 } },
336
+ },
337
+ };
338
+ const SCALING_JSON_SCHEMA = {
339
+ description: 'Activation and autoscaling, the same object as the apps API: activation always (default), http (scale to ' +
340
+ 'zero when idle) or manual; replica bounds; autoscaling and rollout. Applied by a deploy that may take production. ' +
341
+ 'Keys declared here are managed by this file.',
342
+ type: 'object',
343
+ additionalProperties: false,
344
+ properties: {
345
+ activation: { enum: ['always', 'http', 'manual'] },
346
+ minReplicas: { enum: [0, 1] },
347
+ maxReplicas: { type: 'integer', minimum: 1, maximum: APP_SCALING_MAX_REPLICAS },
348
+ idleTimeoutSeconds: { type: 'integer', minimum: 300, maximum: APP_SCALING_MAX_DELAY_SECONDS },
349
+ activationTimeoutSeconds: { type: 'integer', minimum: 5, maximum: 300 },
350
+ scaleDownStabilizationSeconds: { type: 'integer', minimum: 0, maximum: APP_SCALING_MAX_DELAY_SECONDS },
351
+ autoscaling: {
352
+ type: ['object', 'null'],
353
+ additionalProperties: false,
354
+ properties: {
355
+ minReplicas: { type: 'integer', minimum: 1, maximum: APP_SCALING_MAX_REPLICAS },
356
+ cpuUtilizationPercent: nullableInt(APP_AUTOSCALING_CPU_PERCENT_RANGE[0], APP_AUTOSCALING_CPU_PERCENT_RANGE[1]),
357
+ concurrencyPerReplica: nullableInt(1, APP_AUTOSCALING_MAX_CONCURRENCY),
358
+ scaleUpStabilizationSeconds: { type: 'integer', minimum: 0, maximum: APP_AUTOSCALING_MAX_STABILIZATION_SECONDS },
359
+ scaleDownStabilizationSeconds: { type: 'integer', minimum: 0, maximum: APP_AUTOSCALING_MAX_STABILIZATION_SECONDS },
360
+ },
361
+ },
362
+ rollout: {
363
+ type: ['object', 'null'],
364
+ additionalProperties: false,
365
+ properties: {
366
+ maxSurge: nullableInt(1, APP_ROLLOUT_MAX_FIGURE),
367
+ maxUnavailable: nullableInt(0, APP_ROLLOUT_MAX_FIGURE),
368
+ progressDeadlineSeconds: nullableInt(APP_ROLLOUT_PROGRESS_DEADLINE_RANGE[0], APP_ROLLOUT_PROGRESS_DEADLINE_RANGE[1]),
369
+ },
370
+ },
371
+ },
372
+ };
373
+ /**
374
+ * JSON Schema (draft-07) of inquir.yaml, for editor completion and
375
+ * validation (`# yaml-language-server: $schema=…`). The repository keeps it
376
+ * as schemas/inquir.yaml.json (a test keeps the two equal, and another runs
377
+ * one fixture set through this schema and the platform validator); apps'
378
+ * `services` is described loosely here, its validator is the platform's.
379
+ * Unknown keys are refused everywhere a typo would silently drop packages.
380
+ */
381
+ export const INQUIR_YAML_JSON_SCHEMA = {
382
+ $schema: 'http://json-schema.org/draft-07/schema#',
383
+ $id: 'https://inquir.org/schemas/inquir.yaml.json',
384
+ title: 'inquir.yaml',
385
+ description: 'Inquir Compute configuration: function build settings (system packages) and the application manifest.',
386
+ type: ['object', 'null'],
387
+ additionalProperties: false,
388
+ properties: {
389
+ version: { const: 1, description: 'Application manifest version (apps)' },
390
+ services: {
391
+ type: 'object',
392
+ description: 'Application services (apps): services.web.build or imageRef, runtime, env, scale, networkPolicy, scaling, location',
393
+ properties: {
394
+ web: { $ref: '#/definitions/service' },
395
+ },
396
+ },
397
+ build: { $ref: '#/definitions/build', description: 'Build settings for every function deployed from this project or directory' },
398
+ functions: {
399
+ type: ['object', 'null'],
400
+ description: 'Per-function settings; a function entry replaces the project default (no merge)',
401
+ additionalProperties: {
402
+ type: ['object', 'null'],
403
+ additionalProperties: false,
404
+ properties: { build: { $ref: '#/definitions/build' } },
405
+ },
406
+ },
407
+ },
408
+ definitions: {
409
+ service: {
410
+ description: 'One service: services.web of inquir.yaml, and an inline service of inquir-compose.yaml (the same block).',
411
+ type: 'object',
412
+ properties: {
413
+ build: {
414
+ type: 'object',
415
+ description: 'The Dockerfile build: context (a folder inside the source), dockerfile (relative to the context), target, args',
416
+ properties: {
417
+ context: { type: 'string', minLength: 1, maxLength: 1024 },
418
+ dockerfile: { type: 'string', minLength: 1, maxLength: 1024 },
419
+ target: { type: 'string', minLength: 1, maxLength: 128 },
420
+ args: { type: 'object', maxProperties: 32, additionalProperties: { type: 'string', maxLength: 4096 } },
421
+ },
422
+ },
423
+ env: {
424
+ type: 'object',
425
+ description: 'Non-secret defaults, frozen with the build; application variables win. Never secrets: inquir.yaml is committed.',
426
+ additionalProperties: { type: 'string', maxLength: 32768 },
427
+ },
428
+ runtime: {
429
+ type: 'object',
430
+ description: 'The pod template, frozen with each release (port, ports, volumes, healthcheck, hooks, roles, ...)',
431
+ properties: { roles: { $ref: '#/definitions/roles' }, hooks: { $ref: '#/definitions/hooks' } },
432
+ },
433
+ scale: { $ref: '#/definitions/scale' },
434
+ imageRef: {
435
+ type: 'string',
436
+ maxLength: 512,
437
+ pattern: PINNED_IMAGE_REF_PATTERN,
438
+ description: 'Deploy this registry image instead of building one, pinned by digest (registry/repository[:tag]@sha256:<digest>; ' +
439
+ 'docker buildx imagetools inspect <image> prints it). runtime, env and scale apply to it as to a built image. ' +
440
+ 'Exclusive with build.',
441
+ },
442
+ networkPolicy: { $ref: '#/definitions/networkPolicy' },
443
+ scaling: { $ref: '#/definitions/scaling' },
444
+ location: {
445
+ type: 'string',
446
+ minLength: 1,
447
+ maxLength: 32,
448
+ description: 'Where the service runs: auto (any location) or a location id this platform offers, for example nl or ru ' +
449
+ '(checked at deploy time). Managed by this file when declared.',
450
+ },
451
+ },
452
+ not: { required: ['imageRef', 'build'] },
453
+ },
454
+ scale: SCALE_JSON_SCHEMA,
455
+ networkPolicy: NETWORK_POLICY_JSON_SCHEMA,
456
+ scaling: SCALING_JSON_SCHEMA,
457
+ roles: ROLES_JSON_SCHEMA,
458
+ hooks: HOOKS_JSON_SCHEMA,
459
+ build: {
460
+ type: ['object', 'null'],
461
+ additionalProperties: false,
462
+ properties: {
463
+ system: { $ref: '#/definitions/system' },
464
+ dependencies: {
465
+ type: ['array', 'null'],
466
+ maxItems: 200,
467
+ items: { type: 'string', minLength: 1, maxLength: 512 },
468
+ description: 'Language packages, the same list for every runtime: node name@version (npm), python a pip requirement such as name==version, go module@version. Merged into package.json / requirements.txt / go.mod for the build; the same package declared there with another version is an error. Where the platform does not enable it yet, a deploy ignores it with a warning.',
469
+ },
470
+ },
471
+ },
472
+ system: {
473
+ description: 'OS packages installed into the function image (Debian bookworm; Node.js and Python today, Go coming soon). Removing the block removes them on the next deploy.',
474
+ type: ['object', 'null'],
475
+ additionalProperties: false,
476
+ properties: {
477
+ presets: { type: ['array', 'null'], maxItems: SYSTEM_MAX_PRESETS, uniqueItems: true, items: presetItemSchema },
478
+ packages: {
479
+ type: ['array', 'null'],
480
+ maxItems: SYSTEM_MAX_PACKAGES,
481
+ uniqueItems: true,
482
+ items: {
483
+ type: 'string',
484
+ pattern: SYSTEM_PACKAGE_NAME_PATTERN,
485
+ not: { pattern: SYSTEM_PACKAGE_DENYLIST_PATTERN },
486
+ description: 'Debian package, optionally name=version (daemons, privilege tools, kernels and package tooling are refused)',
487
+ },
488
+ },
489
+ },
490
+ },
491
+ },
492
+ };
493
+ /** The keys of one service block (inquir.yaml services.web; the platform's INQUIR_SERVICE_KEYS). */
494
+ export const INQUIR_SERVICE_KEYS = ['build', 'imageRef', 'runtime', 'env', 'scale', 'networkPolicy', 'scaling', 'location'];
495
+ /** The stack keys an inquir-compose service entry adds (the platform's STACK_KEYS). */
496
+ export const COMPOSE_STACK_KEYS = ['path', 'title', 'dependsOn', 'variables', 'buildArgs'];
497
+ const composeText = {
498
+ anyOf: [
499
+ { type: 'string', minLength: 1, maxLength: 8192 },
500
+ { type: 'object', additionalProperties: false, required: ['en', 'ru'],
501
+ properties: { en: { type: 'string', minLength: 1, maxLength: 8192 }, ru: { type: 'string', minLength: 1, maxLength: 8192 } } },
502
+ ],
503
+ };
504
+ const composeServiceKey = '^[a-z][a-z0-9-]{0,30}$';
505
+ /**
506
+ * JSON Schema (draft-07) of inquir-compose.yaml, for editors
507
+ * (docs/roadmap/INQUIR_COMPOSE.md §3). An inline service is inquir.yaml's
508
+ * definitions.service plus the stack keys; references ({{...}}) and the
509
+ * cross-field rules are the platform validator's (POST /v1/compose/validate).
510
+ */
511
+ export const INQUIR_COMPOSE_YAML_JSON_SCHEMA = {
512
+ $schema: 'http://json-schema.org/draft-07/schema#',
513
+ $id: 'https://inquir.org/schemas/inquir-compose.yaml.json',
514
+ title: 'inquir-compose.yaml',
515
+ description: 'A stack of Inquir services: each a folder with its own inquir.yaml (path) or an inline inquir.yaml services.web block.',
516
+ type: 'object',
517
+ required: ['version', 'services'],
518
+ additionalProperties: false,
519
+ patternProperties: { '^x-': { description: 'Ignored by the platform: a place for YAML anchors' } },
520
+ properties: {
521
+ version: { const: 1 },
522
+ metadata: {
523
+ type: 'object', additionalProperties: false, required: ['title'],
524
+ properties: {
525
+ title: composeText,
526
+ description: composeText,
527
+ icon: { type: 'string', pattern: '^[a-z][a-z0-9-]{0,31}$' },
528
+ category: { enum: ['database', 'cache', 'web', 'agent', 'bot', 'other'] },
529
+ docsUrl: { type: 'string', pattern: '^https://', maxLength: 2048 },
530
+ notes: { type: 'array', maxItems: 30, items: composeText },
531
+ minPlan: { enum: ['free', 'simple', 'pro', 'enterprise'], description: 'A display hint; the deploy judges the real plan' },
532
+ },
533
+ },
534
+ inputs: {
535
+ type: 'object', maxProperties: 64, description: 'Values asked at deploy time',
536
+ propertyNames: { pattern: '^[A-Za-z_][A-Za-z0-9_]*$' },
537
+ additionalProperties: {
538
+ type: 'object', additionalProperties: false, required: ['label'],
539
+ properties: {
540
+ label: composeText, hint: composeText,
541
+ secret: { type: 'boolean', description: 'Typed at deploy time, stored encrypted, never echoed; no default' },
542
+ required: { type: 'boolean' },
543
+ default: { type: 'string', maxLength: 4096 },
544
+ minLength: { type: 'integer', minimum: 0, maximum: 4096 },
545
+ maxLength: { type: 'integer', minimum: 1, maximum: 4096 },
546
+ options: { type: 'array', minItems: 1, maxItems: 32, items: { type: 'string', minLength: 1, maxLength: 256 } },
547
+ pattern: { enum: ['username', 'hostname', 'email', 'https-url', 'integer', 'csv-integers'] },
548
+ },
549
+ if: { required: ['secret'], properties: { secret: { const: true } } },
550
+ then: { not: { required: ['default'] } },
551
+ },
552
+ },
553
+ generate: {
554
+ type: 'object', maxProperties: 32, description: 'Credentials the platform generates once per stack: {{generated.<key>}}',
555
+ propertyNames: { pattern: '^[a-z][a-z0-9-]{0,63}$' },
556
+ additionalProperties: {
557
+ type: 'object', additionalProperties: false, required: ['bytes', 'encoding'],
558
+ properties: { bytes: { type: 'integer', minimum: 16, maximum: 64 }, encoding: { enum: ['hex', 'base64', 'base64url'] } },
559
+ },
560
+ },
561
+ project: {
562
+ type: 'object', additionalProperties: false,
563
+ properties: { placement: { enum: ['new', 'existing'] }, name: { type: 'string', minLength: 1, maxLength: 64 } },
564
+ },
565
+ defaults: {
566
+ type: 'object', additionalProperties: false,
567
+ description: 'Merged under every inline service: location, networkPolicy, scaling and runtime.resources only',
568
+ properties: {
569
+ location: { type: 'string', minLength: 1, maxLength: 32 },
570
+ networkPolicy: { $ref: '#/definitions/networkPolicy' },
571
+ scaling: { $ref: '#/definitions/scaling' },
572
+ runtime: { type: 'object', additionalProperties: false, properties: { resources: { type: 'object' } } },
573
+ },
574
+ },
575
+ services: {
576
+ type: 'object', minProperties: 1, maxProperties: 32,
577
+ propertyNames: { pattern: composeServiceKey },
578
+ additionalProperties: {
579
+ allOf: [{ $ref: '#/definitions/service' }],
580
+ type: 'object',
581
+ propertyNames: { enum: [...INQUIR_SERVICE_KEYS, ...COMPOSE_STACK_KEYS] },
582
+ properties: {
583
+ path: { type: 'string', minLength: 1, maxLength: 1024, description: 'A folder with its own inquir.yaml (then only stack keys sit next to it)' },
584
+ title: { type: 'string', minLength: 1, maxLength: 80 },
585
+ dependsOn: { type: 'array', maxItems: 32, items: { type: 'string', pattern: composeServiceKey } },
586
+ variables: {
587
+ type: 'object', maxProperties: 128,
588
+ description: 'The application variables; references {{inputs.X}}, {{generated.x}}, {{services.s.privateHost}}, ... resolve here',
589
+ propertyNames: { pattern: '^[A-Za-z_][A-Za-z0-9_]*$' },
590
+ additionalProperties: { type: 'string', maxLength: 32768 },
591
+ },
592
+ buildArgs: {
593
+ type: 'object', maxProperties: 32, description: 'Build arguments for this deploy: no secrets',
594
+ additionalProperties: { type: 'string', maxLength: 4096 },
595
+ },
596
+ },
597
+ },
598
+ },
599
+ entrypoint: { type: 'string', pattern: composeServiceKey, description: 'The public service opened after deploy' },
600
+ files: { type: 'object', description: 'Bundle form: the embedded build tree, path -> content', additionalProperties: { type: 'string' } },
601
+ },
602
+ // inquir.yaml's definitions, copied so the file stands alone (editors resolve no remote $ref).
603
+ definitions: INQUIR_YAML_JSON_SCHEMA.definitions,
604
+ };
605
+ //# sourceMappingURL=system-packages.js.map