@spacefast/common 0.0.12 → 0.0.13
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/dist/contracts/access.d.ts +386 -1201
- package/dist/contracts/access.js +240 -1057
- package/dist/contracts/activity.d.ts +1 -1
- package/dist/contracts/activity.js +6 -14
- package/dist/contracts/api-keys.d.ts +16 -0
- package/dist/contracts/api-keys.js +2 -0
- package/dist/contracts/archives.d.ts +1 -2
- package/dist/contracts/archives.js +4 -6
- package/dist/contracts/comments.d.ts +58 -85
- package/dist/contracts/comments.js +86 -67
- package/dist/contracts/countries.js +2 -7
- package/dist/contracts/data-source-routes.d.ts +20 -0
- package/dist/contracts/data-source-routes.js +15 -0
- package/dist/contracts/device-auth.d.ts +7 -3
- package/dist/contracts/enums.d.ts +2 -4
- package/dist/contracts/enums.js +3 -8
- package/dist/contracts/error-code-meta.d.ts +17 -20
- package/dist/contracts/error-code-meta.js +8 -5
- package/dist/contracts/error-codes.d.ts +1 -1
- package/dist/contracts/error-codes.js +4 -5
- package/dist/contracts/events.d.ts +13 -13
- package/dist/contracts/execution.d.ts +212 -0
- package/dist/contracts/execution.js +288 -0
- package/dist/contracts/feature-lifecycle.d.ts +21 -167
- package/dist/contracts/feature-lifecycle.js +27 -173
- package/dist/contracts/features.d.ts +13 -115
- package/dist/contracts/features.js +1 -31
- package/dist/contracts/functions.d.ts +729 -0
- package/dist/contracts/functions.js +485 -0
- package/dist/contracts/git.d.ts +1 -1
- package/dist/contracts/grants.d.ts +1158 -0
- package/dist/contracts/grants.js +696 -0
- package/dist/contracts/ids.d.ts +5 -3
- package/dist/contracts/ids.js +5 -3
- package/dist/contracts/mcp.d.ts +6 -6
- package/dist/contracts/oauth-resources.d.ts +5 -5
- package/dist/contracts/oauth-resources.js +1 -0
- package/dist/contracts/operations.d.ts +2 -2
- package/dist/contracts/pages.d.ts +6 -14
- package/dist/contracts/pages.js +6 -23
- package/dist/contracts/plan-policy.d.ts +1 -8
- package/dist/contracts/plan-policy.js +1 -4
- package/dist/contracts/platform.d.ts +78 -30
- package/dist/contracts/platform.js +59 -12
- package/dist/contracts/push-new.d.ts +26 -2
- package/dist/contracts/push-new.js +8 -0
- package/dist/contracts/quotas.d.ts +0 -1
- package/dist/contracts/quotas.js +0 -5
- package/dist/contracts/repository-connections.d.ts +1 -1
- package/dist/contracts/resources.d.ts +10 -66
- package/dist/contracts/resources.js +4 -10
- package/dist/contracts/runtime-api.d.ts +558 -265
- package/dist/contracts/runtime-api.js +178 -91
- package/dist/contracts/runtime-app.d.ts +138 -0
- package/dist/contracts/runtime-app.js +21 -0
- package/dist/contracts/sf-config-v1.d.ts +5 -0
- package/dist/contracts/sites.d.ts +5 -0
- package/dist/contracts/sites.js +12 -1
- package/dist/contracts/space-config.d.ts +46 -116
- package/dist/contracts/space-config.js +320 -24
- package/dist/contracts/spaces.d.ts +253 -158
- package/dist/contracts/spaces.js +68 -54
- package/dist/contracts/superadmin-emails.d.ts +2 -2
- package/dist/contracts/superadmin-spaces.d.ts +15 -130
- package/dist/contracts/superadmin-spaces.js +7 -0
- package/dist/contracts/tags.d.ts +23 -23
- package/dist/contracts/teams.d.ts +9 -9
- package/dist/contracts/transfers.d.ts +0 -1
- package/dist/contracts/zero.d.ts +195 -273
- package/dist/contracts/zero.js +78 -206
- package/dist/dashboard-paths/index.d.ts +2 -2
- package/dist/dashboard-paths/index.js +1 -0
- package/dist/docs/agent-prose.js +10 -8
- package/dist/docs/agent-setup.d.ts +2 -2
- package/dist/docs/agent-setup.js +11 -9
- package/dist/docs/agent-solutions.js +1 -1
- package/dist/docs/catalog.d.ts +28 -28
- package/dist/docs/catalog.js +29 -29
- package/dist/docs/error-docs.js +23 -27
- package/dist/utils/asset-fingerprint.d.ts +11 -0
- package/dist/utils/asset-fingerprint.js +46 -0
- package/dist/utils/auth-redirect.d.ts +1 -3
- package/dist/utils/auth-redirect.js +1 -21
- package/dist/utils/build-settings.d.ts +2 -0
- package/dist/utils/build-settings.js +61 -9
- package/dist/utils/credential-policy.d.ts +1 -1
- package/dist/utils/credential-policy.js +4 -0
- package/dist/utils/egress-policy.fixtures.json +1 -1
- package/dist/utils/grants.d.ts +53 -0
- package/dist/utils/grants.js +160 -0
- package/dist/utils/local-space-state.js +1 -0
- package/dist/utils/pages.d.ts +11 -5
- package/dist/utils/pages.js +19 -32
- package/dist/utils/publish-policy.d.ts +34 -4
- package/dist/utils/publish-policy.js +132 -61
- package/dist/utils/query-keys.d.ts +1 -6
- package/dist/utils/query-keys.js +1 -6
- package/dist/utils/space-config.d.ts +5 -1
- package/dist/utils/space-config.js +35 -0
- package/dist/utils/static-runtime-policy.d.ts +5 -0
- package/dist/utils/static-runtime-policy.js +54 -10
- package/dist/utils/upload-session.d.ts +3 -0
- package/dist/utils/upload-session.js +31 -0
- package/package.json +2 -1
- package/dist/utils/access-grant.d.ts +0 -14
- package/dist/utils/access-grant.js +0 -88
- package/dist/utils/access-match.d.ts +0 -46
- package/dist/utils/access-match.fixtures.json +0 -513
- package/dist/utils/access-match.js +0 -312
- package/dist/utils/access-verdict.fixtures.json +0 -421
- package/dist/utils/sf-config-v1.d.ts +0 -2
- package/dist/utils/sf-config-v1.fixtures.json +0 -9
- package/dist/utils/sf-config-v1.js +0 -551
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
2
|
+
import { accessFenceKindSchema } from "./access.js";
|
|
3
|
+
import { functionsRuntimeConfigSchema } from "./functions.js";
|
|
4
|
+
import { grantSchema } from "./grants.js";
|
|
3
5
|
import { conventionFilesSchema, manifestFileSchema } from "./internal.js";
|
|
4
6
|
import { runtimePagesSchema } from "./pages.js";
|
|
5
7
|
import { zeroEndpointSchema, zeroRuntimeConfigSchema } from "./zero.js";
|
|
@@ -57,15 +59,6 @@ export const runtimeVersionCreateRequestSchema = z.object({
|
|
|
57
59
|
files: z.array(manifestFileSchema),
|
|
58
60
|
retained_files: z.array(manifestFileSchema).default([]),
|
|
59
61
|
reusable_version_id: z.string().min(1).optional(),
|
|
60
|
-
// "declared" sessions validate every PUT against the declared manifest.
|
|
61
|
-
// "open" sessions (internal-docs/platform.md "Upload Contract" shape 2) have
|
|
62
|
-
// no manifest: the runtime enforces path policy and the session caps per
|
|
63
|
-
// PUT, computes streaming hashes, and finalize derives the manifest.
|
|
64
|
-
// Plan-policy caps ride in session state, never in the upload JWT, and are
|
|
65
|
-
// valid only on open sessions.
|
|
66
|
-
session_mode: z.enum(["declared", "open"]).default("declared"),
|
|
67
|
-
max_total_bytes: z.number().int().positive().optional(),
|
|
68
|
-
max_file_count: z.number().int().positive().optional(),
|
|
69
62
|
// Session state stores the upload truth (spec "Upload Contract"): the version's
|
|
70
63
|
// manifest hash and the draft expiry so resume answers come from runtime state.
|
|
71
64
|
manifest_hash: z.string().optional(),
|
|
@@ -83,7 +76,6 @@ export const runtimeUploadSessionDescriptorSchema = z.object({
|
|
|
83
76
|
upload_id: z.string().min(1),
|
|
84
77
|
space_id: z.string().min(1),
|
|
85
78
|
version_id: z.string().min(1),
|
|
86
|
-
session_mode: z.literal("declared"),
|
|
87
79
|
expires_at: z.string(),
|
|
88
80
|
manifest_hash: z.string().optional(),
|
|
89
81
|
files: z.array(manifestFileSchema),
|
|
@@ -108,7 +100,6 @@ export const runtimeUploadSessionResponseSchema = z.object({
|
|
|
108
100
|
space_id: z.string(),
|
|
109
101
|
version_id: z.string(),
|
|
110
102
|
upload_id: z.string(),
|
|
111
|
-
session_mode: z.enum(["declared", "open"]),
|
|
112
103
|
created_at: z.string().nullable(),
|
|
113
104
|
expires_at: z.string().nullable(),
|
|
114
105
|
manifest_hash: z.string().nullable(),
|
|
@@ -118,39 +109,80 @@ export const runtimeUploadSessionResponseSchema = z.object({
|
|
|
118
109
|
sha256: z.string().optional(),
|
|
119
110
|
uploaded: z.boolean(),
|
|
120
111
|
})),
|
|
121
|
-
// Declared paths the runtime has not committed yet
|
|
112
|
+
// Declared paths the runtime has not committed yet.
|
|
122
113
|
pending_paths: z.array(z.string()),
|
|
123
114
|
// Staged chunked-upload parts by canonical path (contiguity is checked at complete).
|
|
124
115
|
chunks: z.record(z.string(), z.array(z.number().int().positive())),
|
|
125
116
|
});
|
|
126
|
-
// Route-pointer config is pure serving policy
|
|
127
|
-
//
|
|
128
|
-
//
|
|
129
|
-
|
|
130
|
-
|
|
117
|
+
// Route-pointer config is pure serving policy plus the anonymous claim
|
|
118
|
+
// countdown. Per-version serving behavior (index/fallback/listing) remains a
|
|
119
|
+
// version artifact concern.
|
|
120
|
+
export const visitorJwkSchema = z.object({
|
|
121
|
+
kty: z.literal("OKP"),
|
|
122
|
+
crv: z.literal("Ed25519"),
|
|
123
|
+
kid: z.string().min(1),
|
|
124
|
+
alg: z.literal("EdDSA"),
|
|
125
|
+
x: z.string().min(1),
|
|
126
|
+
use: z.literal("sig").optional(),
|
|
127
|
+
});
|
|
128
|
+
export const visitorJwksSchema = z.object({
|
|
129
|
+
keys: z.array(visitorJwkSchema).min(1),
|
|
130
|
+
});
|
|
131
|
+
export const runtimePublicExposureDescriptorSchema = z.object({
|
|
132
|
+
v: z.number().int().positive(),
|
|
133
|
+
public: z.boolean(),
|
|
134
|
+
authorizationDigest: z.string().regex(/^[a-f0-9]{64}$/),
|
|
135
|
+
contentTypes: z.array(z.string()).nullable(),
|
|
136
|
+
externalProxy: z.boolean(),
|
|
137
|
+
unmodeled: z.string(),
|
|
138
|
+
});
|
|
139
|
+
export const runtimeAuthorizationProjectionSchema = z
|
|
140
|
+
.object({
|
|
141
|
+
generation: z.number().int().nonnegative(),
|
|
142
|
+
// Browser sessions follow their still-live authority references across
|
|
143
|
+
// ordinary policy/ownership projections. Only an explicit logout-all
|
|
144
|
+
// rotation invalidates every otherwise-valid session.
|
|
145
|
+
sessionVersion: z.number().int().nonnegative(),
|
|
146
|
+
fence: accessFenceKindSchema,
|
|
147
|
+
acquireUrl: z.string().url(),
|
|
148
|
+
spaceClaimed: z.boolean(),
|
|
149
|
+
grants: z.array(grantSchema.extend({
|
|
150
|
+
// The durable browser session records this generation for the exact
|
|
151
|
+
// authority it acquired. Rotating or editing one credential Grant
|
|
152
|
+
// therefore removes only that authority from the session.
|
|
153
|
+
generation: z.number().int().positive(),
|
|
154
|
+
})),
|
|
155
|
+
})
|
|
156
|
+
.strict();
|
|
131
157
|
const runtimeRouteConfigSchema = z.object({
|
|
132
|
-
//
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
|
|
138
|
-
//
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
|
|
158
|
+
// Canonical scoped admission projection. When present it is the sole serving
|
|
159
|
+
// authority; the legacy rule document below is ignored.
|
|
160
|
+
authorization: runtimeAuthorizationProjectionSchema.nullable().optional(),
|
|
161
|
+
// Digest of every input that can change anonymous/public exposure (canonical
|
|
162
|
+
// authorization boundaries, content types, proxy entitlement, and
|
|
163
|
+
// unknown serving keys). Authority-only rotation deliberately leaves it
|
|
164
|
+
// stable so Link/Person changes do not block on an unnecessary edge purge.
|
|
165
|
+
public_exposure_digest: z
|
|
166
|
+
.string()
|
|
167
|
+
.regex(/^[a-f0-9]{64}$/)
|
|
168
|
+
.optional(),
|
|
169
|
+
// The digest detects equality; the descriptor preserves enough structure for
|
|
170
|
+
// the callback consumer to distinguish widening from narrowing without
|
|
171
|
+
// reconstructing a previous config from mutable control-plane state.
|
|
172
|
+
public_exposure: runtimePublicExposureDescriptorSchema.optional(),
|
|
173
|
+
// Monotonic authorization projection generation. Short-lived handoffs are
|
|
174
|
+
// bound to this exact generation, Space, and host. Browser sessions use the
|
|
175
|
+
// projection's independent sessionVersion revocation floor.
|
|
176
|
+
projection_generation: z.number().int().nonnegative().nullable().optional(),
|
|
177
|
+
// First-party visitor-token verification is explicit.
|
|
178
|
+
visitor_issuer: z.string().min(1).optional(),
|
|
179
|
+
visitor_jwks: visitorJwksSchema.optional(),
|
|
148
180
|
// Anonymous claim-window countdown (ISO timestamp), compiled into serving
|
|
149
181
|
// state so the runtime can render the expiry-rescue banner for visitors
|
|
150
182
|
// holding the claim-link viewer session. Null/absent once claimed.
|
|
151
183
|
anonymous_expires_at: z.string().nullable().optional(),
|
|
152
184
|
// Serve-time content-type allowlist. Generic serving policy: the engine has
|
|
153
|
-
// no notion of WHY a
|
|
185
|
+
// no notion of WHY a file type is blocked — it refuses (403, blocked_message
|
|
154
186
|
// body) any file whose stored Content-Type matches no pattern. Patterns are
|
|
155
187
|
// exact types or `prefix/*` wildcards ("text/*"). The control plane pushes
|
|
156
188
|
// it for unclaimed anonymous spaces (no opaque binaries pre-claim); explicit
|
|
@@ -169,15 +201,15 @@ const runtimeRouteConfigSchema = z.object({
|
|
|
169
201
|
// in V1 (set via the superadmin admission endpoint); absent means the
|
|
170
202
|
// env-knob default applies.
|
|
171
203
|
admission: z.object({ concurrency: z.number().int().positive() }).optional(),
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
204
|
+
// Same-host production tag JavaScript. It rides the mutable route projection
|
|
205
|
+
// so private Spaces never fetch an anonymously readable per-Space artifact.
|
|
206
|
+
tag_sdk: z
|
|
207
|
+
.object({
|
|
208
|
+
revision: z.string().min(1),
|
|
209
|
+
body: z.string().max(5 * 1024 * 1024),
|
|
210
|
+
})
|
|
211
|
+
.nullable()
|
|
212
|
+
.optional(),
|
|
181
213
|
// Serve-time plan entitlements (proxy-routes.md: "the rule stays in your
|
|
182
214
|
// config and activates the moment you upgrade — no redeploy needed"). Stored
|
|
183
215
|
// per space beside `policy`; a `planGated` compiled proxy rule
|
|
@@ -305,12 +337,11 @@ export const runtimeVersionFinalizeRequestSchema = z.object({
|
|
|
305
337
|
session: runtimeUploadSessionDescriptorSchema.optional(),
|
|
306
338
|
zero_mode: runtimeZeroModeSchema.optional(),
|
|
307
339
|
zero: zeroRuntimeConfigSchema.optional(),
|
|
308
|
-
//
|
|
309
|
-
//
|
|
310
|
-
//
|
|
311
|
-
//
|
|
312
|
-
|
|
313
|
-
ready_at: z.number().int().positive().optional(),
|
|
340
|
+
// Dispatch configuration for a Functions version. Absent for static versions,
|
|
341
|
+
// and absent when a worker was published while no execution host is
|
|
342
|
+
// configured — the version then serves as pure static content, because a
|
|
343
|
+
// config is the only thing that makes the origin dispatch at all.
|
|
344
|
+
functions: functionsRuntimeConfigSchema.optional(),
|
|
314
345
|
convention_files: runtimeConventionFilesSchema.optional(),
|
|
315
346
|
// Finalize-time `{{ vars.NAME }}` substitution output (spec "Variable
|
|
316
347
|
// rules"): substituted bytes replace the served files; the engine keeps the
|
|
@@ -394,6 +425,20 @@ export const runtimeVersionFinalizeRequestSchema = z.object({
|
|
|
394
425
|
})
|
|
395
426
|
.optional(),
|
|
396
427
|
});
|
|
428
|
+
const runtimePublicReadinessStatusSchema = z.union([
|
|
429
|
+
z.literal(200),
|
|
430
|
+
z.literal(301),
|
|
431
|
+
z.literal(302),
|
|
432
|
+
z.literal(303),
|
|
433
|
+
z.literal(307),
|
|
434
|
+
z.literal(308),
|
|
435
|
+
z.literal(401),
|
|
436
|
+
z.literal(403),
|
|
437
|
+
]);
|
|
438
|
+
export const runtimeReadinessTargetSchema = z.object({
|
|
439
|
+
path: z.string().startsWith("/"),
|
|
440
|
+
expected_statuses: z.array(z.union([runtimePublicReadinessStatusSchema, z.literal(404)])).min(1),
|
|
441
|
+
});
|
|
397
442
|
export const runtimeVersionFinalizeResponseSchema = z.object({
|
|
398
443
|
space_id: z.string(),
|
|
399
444
|
version_id: z.string(),
|
|
@@ -405,6 +450,12 @@ export const runtimeVersionFinalizeResponseSchema = z.object({
|
|
|
405
450
|
// Returned by both first and idempotent finalize responses so recovery
|
|
406
451
|
// never needs an already-consumed upload session.
|
|
407
452
|
manifest: z.array(manifestFileSchema).optional(),
|
|
453
|
+
readiness_target: runtimeReadinessTargetSchema,
|
|
454
|
+
activation_event_id: z
|
|
455
|
+
.string()
|
|
456
|
+
.min(1)
|
|
457
|
+
.optional()
|
|
458
|
+
.describe("Stable route_updated event id when finalize also activated a route."),
|
|
408
459
|
});
|
|
409
460
|
export const runtimeRouteUpdateRequestSchema = z.object({
|
|
410
461
|
version_id: z.string().min(1),
|
|
@@ -437,6 +488,11 @@ export const runtimeRouteUpdateResponseSchema = z.object({
|
|
|
437
488
|
// and hostname intent all matched the stored route: nothing was journaled,
|
|
438
489
|
// so callers skip the event drain too.
|
|
439
490
|
unchanged: z.boolean().optional(),
|
|
491
|
+
activation_event_id: z
|
|
492
|
+
.string()
|
|
493
|
+
.min(1)
|
|
494
|
+
.optional()
|
|
495
|
+
.describe("Stable route_updated event id for this exact route command, including retries."),
|
|
440
496
|
});
|
|
441
497
|
export const runtimeHostnameIntentUpdateResponseSchema = z.object({
|
|
442
498
|
space_id: z.string(),
|
|
@@ -467,20 +523,6 @@ export const runtimeRetentionPolicyUpdateResponseSchema = z.object({
|
|
|
467
523
|
space_id: z.string(),
|
|
468
524
|
prunable_count: z.number().int().nonnegative(),
|
|
469
525
|
});
|
|
470
|
-
// Instant per-grant tombstone (access-plan revocation hardening): the
|
|
471
|
-
// control plane's best-effort synchronous call at revoke/unrevoke time,
|
|
472
|
-
// hitting the SAME `revocations.json` the durable `config.revocations` full
|
|
473
|
-
// replace (above) also converges. `grant` must be a `link:`/`invite:`/`svc:`
|
|
474
|
-
// row id — the runtime rejects anything else.
|
|
475
|
-
export const runtimeGrantRevocationRequestSchema = z.object({
|
|
476
|
-
grant: z.string().min(1),
|
|
477
|
-
});
|
|
478
|
-
export const runtimeGrantRevocationResponseSchema = z.object({
|
|
479
|
-
space_id: z.string(),
|
|
480
|
-
target_type: z.literal("grant"),
|
|
481
|
-
grant: z.string(),
|
|
482
|
-
revoked: z.boolean(),
|
|
483
|
-
});
|
|
484
526
|
export const runtimeSpaceDeleteResponseSchema = z.object({
|
|
485
527
|
space_id: z.string(),
|
|
486
528
|
status: z.literal("deleted"),
|
|
@@ -503,11 +545,9 @@ const runtimeExportImportStatusSchema = z.enum([
|
|
|
503
545
|
export const runtimeSpaceExportStartRequestSchema = z
|
|
504
546
|
.object({
|
|
505
547
|
version_ids: z.array(z.string().min(1)).min(1).optional(),
|
|
506
|
-
//
|
|
507
|
-
//
|
|
508
|
-
// space access policy entry. Recorded in stattic.json `includes`.
|
|
548
|
+
// include_files=false produces a metadata-only archive that cannot be
|
|
549
|
+
// imported as a serving Space. Recorded in stattic.json `includes`.
|
|
509
550
|
include_files: z.boolean().optional(),
|
|
510
|
-
include_explicit_config: z.boolean().optional(),
|
|
511
551
|
})
|
|
512
552
|
.strict();
|
|
513
553
|
export const runtimeSpaceExportResponseSchema = z.object({
|
|
@@ -529,10 +569,6 @@ export const runtimeSpaceExportResponseSchema = z.object({
|
|
|
529
569
|
});
|
|
530
570
|
export const runtimeSpaceImportStartRequestSchema = z
|
|
531
571
|
.object({
|
|
532
|
-
// Version installation and target-policy replacement are separate trust
|
|
533
|
-
// decisions. Managed imports always pass false; trusted full-restore tools
|
|
534
|
-
// must opt in explicitly before archive upload.
|
|
535
|
-
install_access_policy: z.boolean().optional(),
|
|
536
572
|
version_id_map: z.record(z.string(), z.string()).optional(),
|
|
537
573
|
// Plan §9 gated activation, extended to import (I-4): shares
|
|
538
574
|
// runtimeZeroModeSchema with runtimeVersionFinalizeRequestSchema.
|
|
@@ -682,6 +718,56 @@ export const runtimeCallbackEventSchema = z.looseObject({
|
|
|
682
718
|
.optional()
|
|
683
719
|
.describe("True when changed_paths is the complete diff, including a known-empty diff. Absent on older engines, where an empty array remains the host-wide fallback."),
|
|
684
720
|
previous_version_id: previousVersionIdSchema,
|
|
721
|
+
previous_public_exposure_digest: z
|
|
722
|
+
.string()
|
|
723
|
+
.min(1)
|
|
724
|
+
.nullable()
|
|
725
|
+
.optional()
|
|
726
|
+
.describe("Public-exposure digest stored before a route config write. Field presence proves the route already existed; null means the previous projection was unreadable."),
|
|
727
|
+
public_exposure_digest: z
|
|
728
|
+
.string()
|
|
729
|
+
.min(1)
|
|
730
|
+
.nullable()
|
|
731
|
+
.optional()
|
|
732
|
+
.describe("Public-exposure digest stored by the route config write; null means the incoming projection was unreadable."),
|
|
733
|
+
previous_public_exposure: runtimePublicExposureDescriptorSchema
|
|
734
|
+
.nullable()
|
|
735
|
+
.optional()
|
|
736
|
+
.describe("Public-exposure descriptor stored before a route config write. Null means the previous projection was unreadable."),
|
|
737
|
+
public_exposure: runtimePublicExposureDescriptorSchema
|
|
738
|
+
.nullable()
|
|
739
|
+
.optional()
|
|
740
|
+
.describe("Public-exposure descriptor stored by the route config write. Null means the incoming projection was unreadable."),
|
|
741
|
+
});
|
|
742
|
+
const runtimeEventDeliveryIdentitySchema = z.object({
|
|
743
|
+
event_id: z.string().min(1),
|
|
744
|
+
delivery_id: z.string().min(1),
|
|
745
|
+
});
|
|
746
|
+
const runtimeEventDrainSessionIdSchema = z.string().min(1).max(128);
|
|
747
|
+
export const runtimeEventsDrainRequestSchema = z
|
|
748
|
+
.object({
|
|
749
|
+
session_id: runtimeEventDrainSessionIdSchema,
|
|
750
|
+
page_id: runtimeEventDrainSessionIdSchema.optional(),
|
|
751
|
+
target_event_id: z.string().min(1).max(128).optional(),
|
|
752
|
+
exclude_deliveries: z
|
|
753
|
+
.array(runtimeEventDeliveryIdentitySchema)
|
|
754
|
+
.max(100)
|
|
755
|
+
.optional()
|
|
756
|
+
.describe("Failed deliveries from the immediately preceding page."),
|
|
757
|
+
finish_session: z.boolean().optional(),
|
|
758
|
+
})
|
|
759
|
+
.superRefine((value, context) => {
|
|
760
|
+
if (value.finish_session === true) {
|
|
761
|
+
if (value.page_id || value.target_event_id || value.exclude_deliveries) {
|
|
762
|
+
context.addIssue({
|
|
763
|
+
code: "custom",
|
|
764
|
+
message: "A finished drain session cannot request a page.",
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
if (!value.page_id)
|
|
770
|
+
context.addIssue({ code: "custom", message: "A drain page requires page_id." });
|
|
685
771
|
});
|
|
686
772
|
export const runtimeEventsDrainResponseSchema = z.object({
|
|
687
773
|
delivered_count: z.number().int().nonnegative(),
|
|
@@ -693,16 +779,33 @@ export const runtimeEventsDrainResponseSchema = z.object({
|
|
|
693
779
|
.optional()
|
|
694
780
|
.describe("Undeliverable callbacks dropped after exceeding the attempt cap."),
|
|
695
781
|
returned_count: z.number().int().nonnegative().optional(),
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
782
|
+
pending_count: z
|
|
783
|
+
.number()
|
|
784
|
+
.int()
|
|
785
|
+
.nonnegative()
|
|
786
|
+
.optional()
|
|
787
|
+
.describe("Journal entries not returned because of the response cap, another active lease, or this session's failed-delivery deferral. Non-zero means a later page or repair session still has work."),
|
|
788
|
+
// The drain is pull-first: the caller IS the control plane and is blocked on
|
|
789
|
+
// this response, so the engine hands its journal back here instead of posting
|
|
790
|
+
// each event over a separate HTTP round trip. Processing replays are no-ops
|
|
791
|
+
// on (event_id, hostname).
|
|
699
792
|
events: z
|
|
700
793
|
.array(z.object({
|
|
794
|
+
delivery_id: z.string().min(1),
|
|
701
795
|
operation_id: z.string().optional(),
|
|
702
796
|
event: runtimeCallbackEventSchema,
|
|
703
797
|
}))
|
|
704
798
|
.optional(),
|
|
705
799
|
});
|
|
800
|
+
export const runtimeEventsAckRequestSchema = z.object({
|
|
801
|
+
session_id: runtimeEventDrainSessionIdSchema,
|
|
802
|
+
deliveries: z.array(runtimeEventDeliveryIdentitySchema).max(100),
|
|
803
|
+
});
|
|
804
|
+
export const runtimeEventsAckResponseSchema = z.object({
|
|
805
|
+
acknowledged_count: z.number().int().nonnegative(),
|
|
806
|
+
idempotent_count: z.number().int().nonnegative(),
|
|
807
|
+
stale_count: z.number().int().nonnegative(),
|
|
808
|
+
});
|
|
706
809
|
// Engine job runner (plan §22, Placement V2): the box-local job runner behind
|
|
707
810
|
// the two-lane tick. The control plane creates a job, drives it with repeated
|
|
708
811
|
// ticks (kick-on-enqueue; the site-cron watchdog ticks the same route), and
|
|
@@ -751,19 +854,3 @@ export const runtimeEngineJobTickResponseSchema = z.object({
|
|
|
751
854
|
job: runtimeEngineJobRecordSchema.nullable().optional(),
|
|
752
855
|
drained: z.boolean().optional(),
|
|
753
856
|
});
|
|
754
|
-
// The management pull action for the Views panel (access-plan §5.6b, X-37):
|
|
755
|
-
// `GET /access-events?file&offset&limit` — a cursor-resumed read of the
|
|
756
|
-
// runtime's own per-hostname NDJSON access-event journal. `cursor` is the
|
|
757
|
-
// position after the last returned event (feed it back verbatim); `done` is
|
|
758
|
-
// false only when the response was truncated by `limit`; `dropped` totals the
|
|
759
|
-
// writer's `.dropped` sidecars (events skipped past the per-file byte cap).
|
|
760
|
-
export const runtimeAccessEventsCursorSchema = z.object({
|
|
761
|
-
file: z.string().min(1).nullable(),
|
|
762
|
-
offset: z.number().int().nonnegative(),
|
|
763
|
-
});
|
|
764
|
-
export const runtimeAccessEventsResponseSchema = z.object({
|
|
765
|
-
events: z.array(accessEventSchema).default([]),
|
|
766
|
-
cursor: runtimeAccessEventsCursorSchema,
|
|
767
|
-
done: z.boolean(),
|
|
768
|
-
dropped: z.number().int().nonnegative().default(0),
|
|
769
|
-
});
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* The one answer to "what is running on this space".
|
|
4
|
+
*
|
|
5
|
+
* A space is exactly one runtime kind — `versionRuntimeKind()` returns a single
|
|
6
|
+
* value and a publish carrying both declarations is refused at finalize — so
|
|
7
|
+
* this is a discriminated union rather than a bag of optional per-product
|
|
8
|
+
* fields. Anything that is not an execution tier has no member here and reads
|
|
9
|
+
* as `null`, which is the overwhelmingly common answer: a static space is not a
|
|
10
|
+
* degenerate app, it is the absence of one.
|
|
11
|
+
*
|
|
12
|
+
* It lives in its own module because it is the only place that needs to know
|
|
13
|
+
* about both products at once. `spaces.ts` imports it to describe runtime
|
|
14
|
+
* status; neither `zero.ts` nor `functions.ts` has to learn about the other.
|
|
15
|
+
*/
|
|
16
|
+
export declare const runtimeAppSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
17
|
+
runtimeKind: z.ZodLiteral<"zero">;
|
|
18
|
+
artifactId: z.ZodString;
|
|
19
|
+
appName: z.ZodString;
|
|
20
|
+
serverRuntime: z.ZodLiteral<"quickjs-rust">;
|
|
21
|
+
inspect: z.ZodObject<{
|
|
22
|
+
policy: z.ZodEnum<{
|
|
23
|
+
public: "public";
|
|
24
|
+
private: "private";
|
|
25
|
+
}>;
|
|
26
|
+
}, z.core.$strict>;
|
|
27
|
+
install: z.ZodObject<{
|
|
28
|
+
runtimeKind: z.ZodLiteral<"zero">;
|
|
29
|
+
engine: z.ZodLiteral<"quickjs-rust">;
|
|
30
|
+
storageRoot: z.ZodLiteral<"__spacefast/zero">;
|
|
31
|
+
artifactPath: z.ZodLiteral<"__spacefast/zero/artifact.json">;
|
|
32
|
+
configPath: z.ZodLiteral<"__spacefast/zero/config.json">;
|
|
33
|
+
binary: z.ZodObject<{
|
|
34
|
+
path: z.ZodLiteral<"__spacefast/zero/bin/stattic-runtime">;
|
|
35
|
+
compatibilityTarget: z.ZodObject<{
|
|
36
|
+
profile: z.ZodLiteral<"wpcloud-linux-x86_64-gnu-v1">;
|
|
37
|
+
os: z.ZodLiteral<"linux">;
|
|
38
|
+
cpu: z.ZodLiteral<"x86_64">;
|
|
39
|
+
libc: z.ZodLiteral<"glibc">;
|
|
40
|
+
linking: z.ZodLiteral<"dynamic">;
|
|
41
|
+
requireExecutableBit: z.ZodLiteral<true>;
|
|
42
|
+
}, z.core.$strict>;
|
|
43
|
+
sha256: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
44
|
+
required: z.ZodLiteral<true>;
|
|
45
|
+
}, z.core.$strict>;
|
|
46
|
+
mysql: z.ZodObject<{
|
|
47
|
+
migrateAtFinalize: z.ZodLiteral<true>;
|
|
48
|
+
blockIncompatibleRollback: z.ZodLiteral<true>;
|
|
49
|
+
}, z.core.$strict>;
|
|
50
|
+
realtime: z.ZodObject<{
|
|
51
|
+
production: z.ZodLiteral<"stattic-central">;
|
|
52
|
+
local: z.ZodLiteral<"foreground-cli-ws">;
|
|
53
|
+
}, z.core.$strict>;
|
|
54
|
+
}, z.core.$strict>;
|
|
55
|
+
tables: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
56
|
+
queries: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
57
|
+
mutations: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
58
|
+
endpoints: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
59
|
+
method: z.ZodEnum<{
|
|
60
|
+
POST: "POST";
|
|
61
|
+
PUT: "PUT";
|
|
62
|
+
GET: "GET";
|
|
63
|
+
HEAD: "HEAD";
|
|
64
|
+
PATCH: "PATCH";
|
|
65
|
+
DELETE: "DELETE";
|
|
66
|
+
OPTIONS: "OPTIONS";
|
|
67
|
+
}>;
|
|
68
|
+
path: z.ZodString;
|
|
69
|
+
}, z.core.$strict>>>;
|
|
70
|
+
sockets: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
71
|
+
variables: z.ZodObject<{
|
|
72
|
+
source: z.ZodLiteral<"stattic-variables">;
|
|
73
|
+
names: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
74
|
+
}, z.core.$strict>;
|
|
75
|
+
realtime: z.ZodObject<{
|
|
76
|
+
mode: z.ZodEnum<{
|
|
77
|
+
"stattic-central": "stattic-central";
|
|
78
|
+
"spacefast-cast": "spacefast-cast";
|
|
79
|
+
"local-dev": "local-dev";
|
|
80
|
+
"local-websocket": "local-websocket";
|
|
81
|
+
}>;
|
|
82
|
+
centralUrl: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
83
|
+
path: z.ZodOptional<z.ZodString>;
|
|
84
|
+
replayPath: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
85
|
+
replayUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
86
|
+
runPath: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
87
|
+
runUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
88
|
+
resourceKey: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
89
|
+
socketPath: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
90
|
+
spaceId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
91
|
+
versionId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
92
|
+
}, z.core.$strict>;
|
|
93
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
94
|
+
runtimeKind: z.ZodLiteral<"functions">;
|
|
95
|
+
artifactId: z.ZodString;
|
|
96
|
+
appName: z.ZodString;
|
|
97
|
+
entry: z.ZodString;
|
|
98
|
+
compatibilityDate: z.ZodString;
|
|
99
|
+
compatibilityFlags: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
100
|
+
routes: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
101
|
+
method: z.ZodDefault<z.ZodNullable<z.ZodEnum<{
|
|
102
|
+
POST: "POST";
|
|
103
|
+
PUT: "PUT";
|
|
104
|
+
GET: "GET";
|
|
105
|
+
HEAD: "HEAD";
|
|
106
|
+
PATCH: "PATCH";
|
|
107
|
+
DELETE: "DELETE";
|
|
108
|
+
OPTIONS: "OPTIONS";
|
|
109
|
+
}>>>;
|
|
110
|
+
path: z.ZodString;
|
|
111
|
+
subtree: z.ZodDefault<z.ZodBoolean>;
|
|
112
|
+
}, z.core.$strict>>>;
|
|
113
|
+
capabilities: z.ZodDefault<z.ZodObject<{
|
|
114
|
+
db: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
115
|
+
fetch: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
116
|
+
auth: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
117
|
+
env: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
118
|
+
realtime: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
119
|
+
logging: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
120
|
+
}, z.core.$strip>>;
|
|
121
|
+
executionState: z.ZodEnum<{
|
|
122
|
+
ready: "ready";
|
|
123
|
+
absent: "absent";
|
|
124
|
+
serving: "serving";
|
|
125
|
+
}>;
|
|
126
|
+
bundleSize: z.ZodNumber;
|
|
127
|
+
variables: z.ZodObject<{
|
|
128
|
+
source: z.ZodLiteral<"spacefast-variables">;
|
|
129
|
+
names: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
130
|
+
}, z.core.$strict>;
|
|
131
|
+
inspect: z.ZodObject<{
|
|
132
|
+
policy: z.ZodEnum<{
|
|
133
|
+
public: "public";
|
|
134
|
+
private: "private";
|
|
135
|
+
}>;
|
|
136
|
+
}, z.core.$strict>;
|
|
137
|
+
}, z.core.$strict>], "runtimeKind">;
|
|
138
|
+
export type RuntimeApp = z.infer<typeof runtimeAppSchema>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { functionsAppSchema } from "./functions.js";
|
|
3
|
+
import { zeroAppSchema } from "./zero.js";
|
|
4
|
+
/**
|
|
5
|
+
* The one answer to "what is running on this space".
|
|
6
|
+
*
|
|
7
|
+
* A space is exactly one runtime kind — `versionRuntimeKind()` returns a single
|
|
8
|
+
* value and a publish carrying both declarations is refused at finalize — so
|
|
9
|
+
* this is a discriminated union rather than a bag of optional per-product
|
|
10
|
+
* fields. Anything that is not an execution tier has no member here and reads
|
|
11
|
+
* as `null`, which is the overwhelmingly common answer: a static space is not a
|
|
12
|
+
* degenerate app, it is the absence of one.
|
|
13
|
+
*
|
|
14
|
+
* It lives in its own module because it is the only place that needs to know
|
|
15
|
+
* about both products at once. `spaces.ts` imports it to describe runtime
|
|
16
|
+
* status; neither `zero.ts` nor `functions.ts` has to learn about the other.
|
|
17
|
+
*/
|
|
18
|
+
export const runtimeAppSchema = z.discriminatedUnion("runtimeKind", [
|
|
19
|
+
zeroAppSchema,
|
|
20
|
+
functionsAppSchema,
|
|
21
|
+
]);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Grant } from "./grants.js";
|
|
1
2
|
export declare const SF_CONFIG_V1_CANONICAL_FILE = "sf.jsonc";
|
|
2
3
|
export declare const SF_CONFIG_V1_FILES: readonly ["sf.jsonc", "spacefast.jsonc", "spacefast.json", "sf.json", ".sf/sf.json", ".sf/config.jsonc", ".sf/config.json"];
|
|
3
4
|
/** Published JSON Schema URL for the strict `sf.jsonc` v1 contract. */
|
|
@@ -26,6 +27,9 @@ export type SfConfigV1 = {
|
|
|
26
27
|
substitute?: {
|
|
27
28
|
files: string[];
|
|
28
29
|
};
|
|
30
|
+
access?: {
|
|
31
|
+
public: string[];
|
|
32
|
+
};
|
|
29
33
|
};
|
|
30
34
|
export type EffectiveConfigV1 = {
|
|
31
35
|
version: 1;
|
|
@@ -41,6 +45,7 @@ export type EffectiveConfigV1 = {
|
|
|
41
45
|
};
|
|
42
46
|
metadata?: SfConfigV1["metadata"];
|
|
43
47
|
substitute?: SfConfigV1["substitute"];
|
|
48
|
+
grants?: Grant[];
|
|
44
49
|
};
|
|
45
50
|
export type SfConfigV1Issue = {
|
|
46
51
|
code: "config_alias" | "config_conflict" | "config_identity_moved" | "config_invalid" | "config_key_removed" | "config_unknown_key" | "serve_index_required" | "template_syntax_retired";
|
|
@@ -407,4 +407,9 @@ export declare const SiteRebalanceResultSchema: z.ZodObject<{
|
|
|
407
407
|
spaceId: z.ZodString;
|
|
408
408
|
operationId: z.ZodString;
|
|
409
409
|
}, z.core.$strip>>;
|
|
410
|
+
warning: z.ZodString;
|
|
411
|
+
domainsRequiringReverification: z.ZodArray<z.ZodObject<{
|
|
412
|
+
spaceId: z.ZodString;
|
|
413
|
+
hostname: z.ZodString;
|
|
414
|
+
}, z.core.$strip>>;
|
|
410
415
|
}, z.core.$strip>;
|
package/dist/contracts/sites.js
CHANGED
|
@@ -135,7 +135,7 @@ export const siteRebalanceRequestSchema = z
|
|
|
135
135
|
.optional()
|
|
136
136
|
.describe("Limit the rebalance to these space ids; omitted means every live space on the site."),
|
|
137
137
|
})
|
|
138
|
-
.describe("Operator-only rebalance trigger: move spaces off this site.");
|
|
138
|
+
.describe("Operator-only rebalance trigger: move spaces off this site. This is the ONLY path that relocates an existing Space, and it is not free — see the reverification warning on the result.");
|
|
139
139
|
export const SiteRebalanceResultSchema = z
|
|
140
140
|
.object({
|
|
141
141
|
siteId: z.string().describe("The site spaces are being moved off."),
|
|
@@ -145,5 +145,16 @@ export const SiteRebalanceResultSchema = z
|
|
|
145
145
|
operationId: z.string().describe("The queued `space_move` operation id (`op_...`)."),
|
|
146
146
|
}))
|
|
147
147
|
.describe("One queued move operation per affected space."),
|
|
148
|
+
warning: z
|
|
149
|
+
.string()
|
|
150
|
+
.describe("Consequence of relocating these Spaces: each hostname is handed to another provider site, which re-runs the provider's domain-exclusivity check and is rejected unless the domain's ownership TXT record is still live in DNS."),
|
|
151
|
+
domainsRequiringReverification: z
|
|
152
|
+
.array(z.object({
|
|
153
|
+
spaceId: z.string().describe("Space the hostname serves."),
|
|
154
|
+
hostname: z
|
|
155
|
+
.string()
|
|
156
|
+
.describe("Custom hostname whose provider ownership check re-runs during the move."),
|
|
157
|
+
}))
|
|
158
|
+
.describe("Live custom hostnames on the moved Spaces. Empty means nothing customer-visible is at risk."),
|
|
148
159
|
})
|
|
149
160
|
.describe("Queued rebalance moves; track each operation for completion.");
|