@spacefast/common 0.0.12 → 0.0.17
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/agents/client-registry.d.ts +22 -0
- package/dist/agents/client-registry.js +41 -0
- package/dist/agents/connect-targets.d.ts +51 -6
- package/dist/agents/connect-targets.js +93 -28
- package/dist/brand.d.ts +0 -11
- package/dist/brand.js +0 -20
- package/dist/config/domains.d.ts +15 -6
- package/dist/config/domains.js +24 -10
- package/dist/config/postgres-budget.d.ts +3 -0
- package/dist/config/postgres-budget.js +6 -1
- package/dist/config/postgres-budget.json +2 -1
- package/dist/contracts/abuse.js +1 -1
- package/dist/contracts/access.d.ts +486 -1196
- package/dist/contracts/access.js +323 -1054
- package/dist/contracts/activity.d.ts +1 -1
- package/dist/contracts/activity.js +11 -15
- package/dist/contracts/api-keys.d.ts +16 -0
- package/dist/contracts/api-keys.js +11 -9
- package/dist/contracts/archives.d.ts +1 -2
- package/dist/contracts/archives.js +15 -17
- package/dist/contracts/beta.js +1 -1
- package/dist/contracts/builds.js +14 -14
- package/dist/contracts/channels.js +2 -2
- package/dist/contracts/comments.d.ts +143 -99
- package/dist/contracts/comments.js +194 -79
- package/dist/contracts/common.d.ts +12 -12
- package/dist/contracts/common.js +33 -30
- package/dist/contracts/continuation.js +5 -5
- 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 +13 -9
- package/dist/contracts/device-auth.js +12 -12
- package/dist/contracts/docs.d.ts +10 -10
- package/dist/contracts/domains.js +39 -33
- package/dist/contracts/enums.d.ts +4 -14
- package/dist/contracts/enums.js +3 -10
- package/dist/contracts/error-code-meta.d.ts +122 -56
- package/dist/contracts/error-code-meta.js +43 -19
- package/dist/contracts/error-codes.d.ts +7 -4
- package/dist/contracts/error-codes.js +48 -24
- package/dist/contracts/events.d.ts +22 -15
- package/dist/contracts/events.js +33 -5
- package/dist/contracts/execution.d.ts +238 -0
- package/dist/contracts/execution.js +309 -0
- package/dist/contracts/feature-lifecycle.d.ts +39 -188
- package/dist/contracts/feature-lifecycle.js +52 -196
- package/dist/contracts/features.d.ts +13 -115
- package/dist/contracts/features.js +5 -35
- package/dist/contracts/functions.d.ts +597 -0
- package/dist/contracts/functions.js +475 -0
- package/dist/contracts/grants.d.ts +1175 -0
- package/dist/contracts/grants.js +783 -0
- package/dist/contracts/ids.d.ts +7 -5
- package/dist/contracts/ids.js +7 -7
- package/dist/contracts/internal.js +2 -2
- package/dist/contracts/mcp.d.ts +17 -556
- package/dist/contracts/mcp.js +9 -103
- package/dist/contracts/me.js +3 -4
- package/dist/contracts/notifications.d.ts +108 -0
- package/dist/contracts/notifications.js +54 -0
- package/dist/contracts/oauth-resources.d.ts +22 -5
- package/dist/contracts/oauth-resources.js +23 -2
- package/dist/contracts/operations.d.ts +0 -48
- package/dist/contracts/operations.js +0 -19
- package/dist/contracts/pages.d.ts +10 -14
- package/dist/contracts/pages.js +17 -21
- 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 +69 -20
- package/dist/contracts/problem-document.d.ts +14 -0
- package/dist/contracts/problem-document.js +35 -0
- package/dist/contracts/push-new.d.ts +41 -2
- package/dist/contracts/push-new.js +4 -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 +16 -71
- package/dist/contracts/resources.js +13 -16
- package/dist/contracts/runtime-api.d.ts +666 -303
- package/dist/contracts/runtime-api.js +272 -113
- package/dist/contracts/runtime-app.d.ts +168 -0
- package/dist/contracts/runtime-app.js +42 -0
- package/dist/contracts/runtime-db.d.ts +424 -0
- package/dist/contracts/runtime-db.js +108 -0
- package/dist/contracts/runtime-storage.d.ts +120 -0
- package/dist/contracts/runtime-storage.js +40 -0
- package/dist/contracts/sf-config-v1.d.ts +54 -1
- package/dist/contracts/sf-config-v1.js +2 -2
- package/dist/contracts/sites.d.ts +6 -0
- package/dist/contracts/sites.js +30 -11
- package/dist/contracts/space-config.d.ts +91 -121
- package/dist/contracts/space-config.js +464 -42
- package/dist/contracts/spaces.d.ts +300 -171
- package/dist/contracts/spaces.js +128 -98
- package/dist/contracts/superadmin-emails.d.ts +2 -2
- package/dist/contracts/superadmin-spaces.d.ts +26 -130
- package/dist/contracts/superadmin-spaces.js +22 -0
- package/dist/contracts/superadmin-tenants.js +4 -4
- package/dist/contracts/superadmin.d.ts +4 -0
- package/dist/contracts/superadmin.js +14 -1
- package/dist/contracts/tags.d.ts +6 -6
- package/dist/contracts/tags.js +1 -1
- package/dist/contracts/teams.d.ts +9 -9
- package/dist/contracts/teams.js +25 -16
- package/dist/contracts/theme-json.js +1 -1
- package/dist/contracts/transfers.d.ts +0 -1
- package/dist/contracts/transfers.js +4 -4
- package/dist/contracts/variables.js +3 -3
- package/dist/contracts/zero.d.ts +384 -596
- package/dist/contracts/zero.js +167 -299
- package/dist/dashboard-paths/index.d.ts +18 -3
- package/dist/dashboard-paths/index.js +19 -0
- package/dist/docs/agent-handoff-document.d.ts +2 -2
- package/dist/docs/agent-handoff-document.js +8 -7
- package/dist/docs/agent-prose.d.ts +22 -3
- package/dist/docs/agent-prose.js +227 -55
- package/dist/docs/agent-setup.d.ts +14 -11
- package/dist/docs/agent-setup.js +289 -61
- package/dist/docs/agent-solutions.d.ts +6 -6
- package/dist/docs/agent-solutions.js +24 -22
- package/dist/docs/catalog.d.ts +53 -98
- package/dist/docs/catalog.js +90 -117
- package/dist/docs/error-docs.js +304 -236
- package/dist/docs/skill-distribution.d.ts +2 -0
- package/dist/docs/skill-distribution.js +7 -4
- package/dist/docs/skills.d.ts +546 -0
- package/dist/docs/skills.js +340 -0
- package/dist/utils/auth-redirect.d.ts +1 -3
- package/dist/utils/auth-redirect.js +1 -21
- package/dist/utils/browser-credential.d.ts +19 -0
- package/dist/utils/browser-credential.js +62 -0
- package/dist/utils/build-settings.d.ts +2 -0
- package/dist/utils/build-settings.js +61 -9
- package/dist/utils/comment-avatars.d.ts +7 -0
- package/dist/utils/comment-avatars.js +42 -0
- package/dist/utils/content-type.d.ts +3 -3
- package/dist/utils/content-type.js +38 -61
- package/dist/utils/credential-policy.d.ts +1 -1
- package/dist/utils/credential-policy.js +4 -0
- package/dist/utils/domain-diagnostics.d.ts +5 -5
- package/dist/utils/domain-diagnostics.js +21 -10
- 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.d.ts +78 -4
- package/dist/utils/local-space-state.js +384 -82
- package/dist/utils/one-shot-replay.d.ts +14 -0
- package/dist/utils/one-shot-replay.js +21 -0
- package/dist/utils/page-preview.d.ts +7 -0
- package/dist/utils/page-preview.js +9 -0
- package/dist/utils/pages.d.ts +2 -5
- package/dist/utils/pages.js +64 -33
- package/dist/utils/publish-form-data.d.ts +22 -0
- package/dist/utils/publish-form-data.js +26 -0
- package/dist/utils/publish-policy.d.ts +34 -4
- package/dist/utils/publish-policy.js +149 -62
- package/dist/utils/query-keys.d.ts +8 -10
- package/dist/utils/query-keys.js +14 -10
- package/dist/utils/runtime-paths.d.ts +3 -0
- package/dist/utils/runtime-paths.js +7 -0
- package/dist/utils/secure-local-file.d.ts +73 -0
- package/dist/utils/secure-local-file.js +1373 -0
- package/dist/utils/space-config.d.ts +17 -4
- package/dist/utils/space-config.js +151 -8
- package/dist/utils/static-runtime-policy.d.ts +5 -0
- package/dist/utils/static-runtime-policy.js +54 -10
- package/dist/utils/storage-policy.d.ts +20 -0
- package/dist/utils/storage-policy.fixtures.json +174 -0
- package/dist/utils/storage-policy.js +193 -0
- package/dist/utils/upload-session.d.ts +15 -1
- package/dist/utils/upload-session.js +68 -2
- package/dist/utils/version-file-browser.d.ts +13 -0
- package/dist/utils/version-file-browser.js +59 -0
- package/package.json +20 -1
- package/dist/contracts/mounts.d.ts +0 -142
- package/dist/contracts/mounts.js +0 -56
- 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/asset-fingerprint.d.ts +0 -53
- package/dist/utils/asset-fingerprint.js +0 -574
- 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
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
// Single source of truth for storage HTTP and object-intake policy.
|
|
2
|
+
//
|
|
3
|
+
// TypeScript adapters import this module directly. The PHP runtime binding is
|
|
4
|
+
// generated into runtime/engine/shared/storage-policy.generated.php by
|
|
5
|
+
// `bun --filter @spacefast/control-plane runtime:codegen-policy`. Both execute
|
|
6
|
+
// the same storage-policy.fixtures.json corpus.
|
|
7
|
+
export const STORAGE_OBJECT_MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
8
|
+
export const STORAGE_OBJECT_MAX_OWNER_BYTES = 100 * 1024 * 1024;
|
|
9
|
+
export const STORAGE_CONTENT_SNIFF_BYTES = 512;
|
|
10
|
+
export const STORAGE_BLOCKED_CONTENT_TYPES = [
|
|
11
|
+
"application/java-archive",
|
|
12
|
+
"application/java-vm",
|
|
13
|
+
"application/vnd.microsoft.portable-executable",
|
|
14
|
+
"application/x-dosexec",
|
|
15
|
+
"application/x-httpd-php",
|
|
16
|
+
"application/x-java-archive",
|
|
17
|
+
"application/x-mach-binary",
|
|
18
|
+
"application/x-msdownload",
|
|
19
|
+
"application/xhtml+xml",
|
|
20
|
+
"text/html",
|
|
21
|
+
];
|
|
22
|
+
export const STORAGE_BLOCKED_CONTENT_TYPE_FRAGMENTS = ["javascript", "ecmascript"];
|
|
23
|
+
export const STORAGE_BLOCKED_MAGIC_HEX = [
|
|
24
|
+
"4d5a",
|
|
25
|
+
"7f454c46",
|
|
26
|
+
"feedface",
|
|
27
|
+
"cefaedfe",
|
|
28
|
+
"feedfacf",
|
|
29
|
+
"cffaedfe",
|
|
30
|
+
"cafebabe",
|
|
31
|
+
];
|
|
32
|
+
export const STORAGE_BLOCKED_TEXT_PREFIXES = ["#!", "<!doctype html", "<html", "<script", "<?php"];
|
|
33
|
+
const BLOCKED_CONTENT_TYPES = new Set(STORAGE_BLOCKED_CONTENT_TYPES);
|
|
34
|
+
export function storageDeclaredTypeBlocked(contentType) {
|
|
35
|
+
const declared = contentType.split(";", 1)[0]?.trim().toLowerCase() ?? "";
|
|
36
|
+
return (BLOCKED_CONTENT_TYPES.has(declared) ||
|
|
37
|
+
STORAGE_BLOCKED_CONTENT_TYPE_FRAGMENTS.some((fragment) => declared.includes(fragment)));
|
|
38
|
+
}
|
|
39
|
+
function bytesStartWithHex(bytes, hex) {
|
|
40
|
+
if (bytes.byteLength < hex.length / 2)
|
|
41
|
+
return false;
|
|
42
|
+
for (let offset = 0; offset < hex.length; offset += 2) {
|
|
43
|
+
if (bytes[offset / 2] !== Number.parseInt(hex.slice(offset, offset + 2), 16)) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
export function storageContentBlocked(contentType, input) {
|
|
50
|
+
if (storageDeclaredTypeBlocked(contentType))
|
|
51
|
+
return true;
|
|
52
|
+
const prefix = input.subarray(0, STORAGE_CONTENT_SNIFF_BYTES);
|
|
53
|
+
if (STORAGE_BLOCKED_MAGIC_HEX.some((magic) => bytesStartWithHex(prefix, magic))) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
const decoded = new TextDecoder().decode(prefix);
|
|
57
|
+
let contentStart = 0;
|
|
58
|
+
while (contentStart < decoded.length) {
|
|
59
|
+
const code = decoded.charCodeAt(contentStart);
|
|
60
|
+
if (code !== 0 && code !== 9 && code !== 10 && code !== 11 && code !== 13 && code !== 32) {
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
contentStart += 1;
|
|
64
|
+
}
|
|
65
|
+
const text = decoded.slice(contentStart).toLowerCase();
|
|
66
|
+
return STORAGE_BLOCKED_TEXT_PREFIXES.some((blocked) => text.startsWith(blocked));
|
|
67
|
+
}
|
|
68
|
+
export function storageParseSingleRange(rangeHeader, size) {
|
|
69
|
+
if (!rangeHeader || rangeHeader.trim() === "" || rangeHeader.includes(","))
|
|
70
|
+
return null;
|
|
71
|
+
const match = /^bytes=(\d*)-(\d*)$/.exec(rangeHeader.trim());
|
|
72
|
+
if (!match || (!match[1] && !match[2]))
|
|
73
|
+
return null;
|
|
74
|
+
if (!match[1]) {
|
|
75
|
+
const suffix = Number(match[2]);
|
|
76
|
+
if (!Number.isSafeInteger(suffix) || suffix <= 0 || size <= 0) {
|
|
77
|
+
return { unsatisfiable: true };
|
|
78
|
+
}
|
|
79
|
+
const start = Math.max(0, size - suffix);
|
|
80
|
+
const end = size - 1;
|
|
81
|
+
return { start, end, header: `bytes=${start}-${end}` };
|
|
82
|
+
}
|
|
83
|
+
const start = Number(match[1]);
|
|
84
|
+
const requestedEnd = match[2] ? Number(match[2]) : size - 1;
|
|
85
|
+
const end = Math.min(requestedEnd, size - 1);
|
|
86
|
+
if (!Number.isSafeInteger(start) ||
|
|
87
|
+
!Number.isSafeInteger(requestedEnd) ||
|
|
88
|
+
start >= size ||
|
|
89
|
+
start > end ||
|
|
90
|
+
size < 0) {
|
|
91
|
+
return { unsatisfiable: true };
|
|
92
|
+
}
|
|
93
|
+
return { start, end, header: `bytes=${start}-${end}` };
|
|
94
|
+
}
|
|
95
|
+
function storageEtagOpaqueTag(etag) {
|
|
96
|
+
const trimmed = etag.trim();
|
|
97
|
+
return /^W\//i.test(trimmed) ? trimmed.slice(2).trim() : trimmed;
|
|
98
|
+
}
|
|
99
|
+
export function storageIfNoneMatchMatches(header, etag) {
|
|
100
|
+
const value = header?.trim() ?? "";
|
|
101
|
+
if (value === "")
|
|
102
|
+
return false;
|
|
103
|
+
if (value === "*")
|
|
104
|
+
return true;
|
|
105
|
+
const target = storageEtagOpaqueTag(etag);
|
|
106
|
+
if (target === "")
|
|
107
|
+
return false;
|
|
108
|
+
return value
|
|
109
|
+
.split(",")
|
|
110
|
+
.map((candidate) => candidate.trim())
|
|
111
|
+
.filter(Boolean)
|
|
112
|
+
.some((candidate) => storageEtagOpaqueTag(candidate) === target);
|
|
113
|
+
}
|
|
114
|
+
const HTTP_MONTHS = [
|
|
115
|
+
"Jan",
|
|
116
|
+
"Feb",
|
|
117
|
+
"Mar",
|
|
118
|
+
"Apr",
|
|
119
|
+
"May",
|
|
120
|
+
"Jun",
|
|
121
|
+
"Jul",
|
|
122
|
+
"Aug",
|
|
123
|
+
"Sep",
|
|
124
|
+
"Oct",
|
|
125
|
+
"Nov",
|
|
126
|
+
"Dec",
|
|
127
|
+
];
|
|
128
|
+
const HTTP_WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
129
|
+
const HTTP_WEEKDAYS_LONG = [
|
|
130
|
+
"Sunday",
|
|
131
|
+
"Monday",
|
|
132
|
+
"Tuesday",
|
|
133
|
+
"Wednesday",
|
|
134
|
+
"Thursday",
|
|
135
|
+
"Friday",
|
|
136
|
+
"Saturday",
|
|
137
|
+
];
|
|
138
|
+
function storageHttpDateTimestamp(weekday, day, month, year, hour, minute, second) {
|
|
139
|
+
if (hour > 23 || minute > 59 || second > 60)
|
|
140
|
+
return null;
|
|
141
|
+
const normalizedSecond = Math.min(second, 59);
|
|
142
|
+
const date = new Date(0);
|
|
143
|
+
date.setUTCFullYear(year, month, day);
|
|
144
|
+
date.setUTCHours(hour, minute, normalizedSecond, 0);
|
|
145
|
+
if (date.getUTCFullYear() !== year ||
|
|
146
|
+
date.getUTCMonth() !== month ||
|
|
147
|
+
date.getUTCDate() !== day ||
|
|
148
|
+
date.getUTCHours() !== hour ||
|
|
149
|
+
date.getUTCMinutes() !== minute ||
|
|
150
|
+
date.getUTCSeconds() !== normalizedSecond ||
|
|
151
|
+
(weekday !== null && date.getUTCDay() !== weekday)) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
return date.getTime() + (second === 60 ? 1_000 : 0);
|
|
155
|
+
}
|
|
156
|
+
// HTTP-date has exactly three accepted wire forms (RFC 9110 §5.6.7). General
|
|
157
|
+
// date parsers also accept relative/free-form input such as `tomorrow`, so
|
|
158
|
+
// validators must parse the grammar and validate its calendar components.
|
|
159
|
+
export function storageParseHttpDate(value) {
|
|
160
|
+
const input = value.trim();
|
|
161
|
+
let match = /^(Sun|Mon|Tue|Wed|Thu|Fri|Sat), (\d{2}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d{2}):(\d{2}):(\d{2}) GMT$/.exec(input);
|
|
162
|
+
if (match) {
|
|
163
|
+
return storageHttpDateTimestamp(HTTP_WEEKDAYS.indexOf(match[1] ?? ""), Number(match[2]), HTTP_MONTHS.indexOf(match[3] ?? ""), Number(match[4]), Number(match[5]), Number(match[6]), Number(match[7]));
|
|
164
|
+
}
|
|
165
|
+
match =
|
|
166
|
+
/^(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday), (\d{2})-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d{2}) (\d{2}):(\d{2}):(\d{2}) GMT$/.exec(input);
|
|
167
|
+
if (match) {
|
|
168
|
+
const now = new Date();
|
|
169
|
+
let year = Math.floor(now.getUTCFullYear() / 100) * 100 + Number(match[4]);
|
|
170
|
+
const candidate = storageHttpDateTimestamp(null, Number(match[2]), HTTP_MONTHS.indexOf(match[3] ?? ""), year, Number(match[5]), Number(match[6]), Number(match[7]));
|
|
171
|
+
const fiftyYearsFromNow = new Date(now);
|
|
172
|
+
fiftyYearsFromNow.setUTCFullYear(now.getUTCFullYear() + 50);
|
|
173
|
+
if (candidate !== null && candidate > fiftyYearsFromNow.getTime())
|
|
174
|
+
year -= 100;
|
|
175
|
+
return storageHttpDateTimestamp(HTTP_WEEKDAYS_LONG.indexOf(match[1] ?? ""), Number(match[2]), HTTP_MONTHS.indexOf(match[3] ?? ""), year, Number(match[5]), Number(match[6]), Number(match[7]));
|
|
176
|
+
}
|
|
177
|
+
match =
|
|
178
|
+
/^(Sun|Mon|Tue|Wed|Thu|Fri|Sat) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (?:([0-9]{2})| ([0-9])) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/.exec(input);
|
|
179
|
+
if (!match)
|
|
180
|
+
return null;
|
|
181
|
+
return storageHttpDateTimestamp(HTTP_WEEKDAYS.indexOf(match[1] ?? ""), Number(match[3] ?? match[4]), HTTP_MONTHS.indexOf(match[2] ?? ""), Number(match[8]), Number(match[5]), Number(match[6]), Number(match[7]));
|
|
182
|
+
}
|
|
183
|
+
export function storageIfRangeMatches(ifRange, etag, lastModified) {
|
|
184
|
+
const value = ifRange.trim();
|
|
185
|
+
if (value === "" || /^W\//i.test(value))
|
|
186
|
+
return false;
|
|
187
|
+
if (value.startsWith('"')) {
|
|
188
|
+
return !/^W\//i.test(etag.trim()) && etag.trim() === value;
|
|
189
|
+
}
|
|
190
|
+
const requestTime = storageParseHttpDate(value);
|
|
191
|
+
const modifiedTime = storageParseHttpDate(lastModified);
|
|
192
|
+
return requestTime !== null && modifiedTime !== null && requestTime >= modifiedTime;
|
|
193
|
+
}
|
|
@@ -19,11 +19,25 @@ export type UploadSessionEvent = {
|
|
|
19
19
|
target: UploadTarget;
|
|
20
20
|
error: unknown;
|
|
21
21
|
};
|
|
22
|
+
/** The RFC 9457 problem document a runtime upload target returns on failure. */
|
|
23
|
+
export type UploadTargetServerError = {
|
|
24
|
+
code: string;
|
|
25
|
+
message: string;
|
|
26
|
+
pointer?: string;
|
|
27
|
+
type?: string;
|
|
28
|
+
details?: unknown;
|
|
29
|
+
suggestions?: readonly string[];
|
|
30
|
+
requestId?: string;
|
|
31
|
+
};
|
|
22
32
|
export declare class UploadTargetError extends Error {
|
|
23
33
|
readonly target: UploadTarget;
|
|
24
34
|
readonly status: number;
|
|
25
|
-
|
|
35
|
+
readonly serverError?: UploadTargetServerError | undefined;
|
|
36
|
+
constructor(target: UploadTarget, status: number, message: string, serverError?: UploadTargetServerError | undefined);
|
|
26
37
|
}
|
|
38
|
+
export declare function uploadPageHasRemainder(page: UploadSession): boolean;
|
|
39
|
+
export declare const UPLOAD_STALLED_RESUME_MAX_ATTEMPTS = 3;
|
|
40
|
+
export declare function uploadQueueAdvanced(before: UploadSession, after: UploadSession | null): boolean;
|
|
27
41
|
export declare function executeUploadSession(input: {
|
|
28
42
|
session: UploadSession;
|
|
29
43
|
targets?: readonly UploadTarget[] | undefined;
|
|
@@ -1,13 +1,78 @@
|
|
|
1
1
|
export class UploadTargetError extends Error {
|
|
2
2
|
target;
|
|
3
3
|
status;
|
|
4
|
-
|
|
4
|
+
serverError;
|
|
5
|
+
constructor(target, status, message, serverError) {
|
|
5
6
|
super(message);
|
|
6
7
|
this.target = target;
|
|
7
8
|
this.status = status;
|
|
9
|
+
this.serverError = serverError;
|
|
8
10
|
this.name = "UploadTargetError";
|
|
9
11
|
}
|
|
10
12
|
}
|
|
13
|
+
function parseUploadTargetServerError(raw) {
|
|
14
|
+
let parsed;
|
|
15
|
+
try {
|
|
16
|
+
parsed = JSON.parse(raw);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
if (!parsed || typeof parsed !== "object") {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
const record = parsed;
|
|
25
|
+
if (typeof record.code !== "string" || typeof record.detail !== "string") {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
const stringField = (name) => typeof record[name] === "string" ? record[name] : undefined;
|
|
29
|
+
const suggestions = Array.isArray(record.suggestions)
|
|
30
|
+
? record.suggestions.filter((entry) => typeof entry === "string")
|
|
31
|
+
: [];
|
|
32
|
+
const pointer = stringField("pointer");
|
|
33
|
+
const type = stringField("type");
|
|
34
|
+
const requestId = stringField("requestId");
|
|
35
|
+
return {
|
|
36
|
+
code: record.code,
|
|
37
|
+
message: record.detail,
|
|
38
|
+
...(pointer ? { pointer } : {}),
|
|
39
|
+
...(type ? { type } : {}),
|
|
40
|
+
...(record.details === undefined ? {} : { details: record.details }),
|
|
41
|
+
...(suggestions.length > 0 ? { suggestions } : {}),
|
|
42
|
+
...(requestId ? { requestId } : {}),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// Manifest paging policy — ONE definition, shared by every uploader (the CLI
|
|
46
|
+
// and the control plane's inline uploader).
|
|
47
|
+
//
|
|
48
|
+
// `targets` is a single instruction page, bounded by the instruction payload
|
|
49
|
+
// budget; `summary.upload` counts the whole declared manifest. A short page
|
|
50
|
+
// therefore means a remainder that only `resume` hands out, and an uploader
|
|
51
|
+
// that stops at the first page finalizes a version the runtime rejects with
|
|
52
|
+
// `version_upload_incomplete`. A complete page means there is nothing left to
|
|
53
|
+
// ask for — don't re-resume to double-check the uploads, since the runtime
|
|
54
|
+
// verifies size and sha256 on every PUT and finalize independently enumerates
|
|
55
|
+
// anything still missing.
|
|
56
|
+
export function uploadPageHasRemainder(page) {
|
|
57
|
+
return page.summary.upload > page.targets.length;
|
|
58
|
+
}
|
|
59
|
+
// Resume mints the next page from runtime session truth, so a converging
|
|
60
|
+
// session always hands back different work. A page that repeats the previous
|
|
61
|
+
// one is a session that is not draining; retry it a bounded number of times,
|
|
62
|
+
// then fail loudly rather than page forever.
|
|
63
|
+
export const UPLOAD_STALLED_RESUME_MAX_ATTEMPTS = 3;
|
|
64
|
+
export function uploadQueueAdvanced(before, after) {
|
|
65
|
+
if (!after || after.targets.length === 0) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
if (after.targets.length < before.targets.length) {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (after.targets.length > before.targets.length) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return after.targets.some((target, index) => target.path !== before.targets[index]?.path);
|
|
75
|
+
}
|
|
11
76
|
async function runConcurrent(items, concurrency, fn) {
|
|
12
77
|
let nextIndex = 0;
|
|
13
78
|
const runWorker = async () => {
|
|
@@ -47,8 +112,9 @@ export async function executeUploadSession(input) {
|
|
|
47
112
|
});
|
|
48
113
|
if (!response.ok) {
|
|
49
114
|
const details = await response.text().catch(() => "");
|
|
115
|
+
const serverError = parseUploadTargetServerError(details);
|
|
50
116
|
const suffix = details.trim() ? `: ${details.trim().slice(0, 1_000)}` : "";
|
|
51
|
-
throw new UploadTargetError(target, response.status, `Upload failed for ${target.path} with ${response.status} ${response.statusText}${suffix}
|
|
117
|
+
throw new UploadTargetError(target, response.status, `Upload failed for ${target.path} with ${response.status} ${response.statusText}${suffix}.`, serverError);
|
|
52
118
|
}
|
|
53
119
|
input.onEvent?.({ type: "target-done", target });
|
|
54
120
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the canonical MIME essence only when browsers may render the bytes
|
|
3
|
+
* on an authenticated origin. Active document formats (HTML, SVG, XML, and
|
|
4
|
+
* scripts) are intentionally absent; `nosniff` is the other half of this
|
|
5
|
+
* contract at the response boundary.
|
|
6
|
+
*/
|
|
7
|
+
export declare function inlineVersionFileContentType(contentType: string | null | undefined): string | null;
|
|
8
|
+
export declare function versionFileContentDisposition(disposition: "attachment" | "inline", filePath: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* A download remains inert even if a user agent ignores attachment handling:
|
|
11
|
+
* the CSP sandbox gives it an opaque origin and permits no script or fetch.
|
|
12
|
+
*/
|
|
13
|
+
export declare function versionFileAttachmentHeaders(filePath: string): Record<string, string>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const INLINE_VERSION_FILE_CONTENT_TYPES = new Set([
|
|
2
|
+
"application/pdf",
|
|
3
|
+
"audio/aac",
|
|
4
|
+
"audio/flac",
|
|
5
|
+
"audio/mp4",
|
|
6
|
+
"audio/mpeg",
|
|
7
|
+
"audio/ogg",
|
|
8
|
+
"audio/opus",
|
|
9
|
+
"audio/wav",
|
|
10
|
+
"audio/webm",
|
|
11
|
+
"audio/x-m4a",
|
|
12
|
+
"audio/x-wav",
|
|
13
|
+
"image/apng",
|
|
14
|
+
"image/avif",
|
|
15
|
+
"image/bmp",
|
|
16
|
+
"image/gif",
|
|
17
|
+
"image/jpeg",
|
|
18
|
+
"image/png",
|
|
19
|
+
"image/vnd.microsoft.icon",
|
|
20
|
+
"image/webp",
|
|
21
|
+
"image/x-icon",
|
|
22
|
+
"video/mp4",
|
|
23
|
+
"video/ogg",
|
|
24
|
+
"video/quicktime",
|
|
25
|
+
"video/webm",
|
|
26
|
+
"video/x-m4v",
|
|
27
|
+
]);
|
|
28
|
+
/**
|
|
29
|
+
* Returns the canonical MIME essence only when browsers may render the bytes
|
|
30
|
+
* on an authenticated origin. Active document formats (HTML, SVG, XML, and
|
|
31
|
+
* scripts) are intentionally absent; `nosniff` is the other half of this
|
|
32
|
+
* contract at the response boundary.
|
|
33
|
+
*/
|
|
34
|
+
export function inlineVersionFileContentType(contentType) {
|
|
35
|
+
const essence = contentType?.split(";", 1)[0]?.trim().toLowerCase() ?? "";
|
|
36
|
+
return INLINE_VERSION_FILE_CONTENT_TYPES.has(essence) ? essence : null;
|
|
37
|
+
}
|
|
38
|
+
function dispositionFilename(filePath) {
|
|
39
|
+
const basename = filePath.split("/").findLast(Boolean) ?? "download";
|
|
40
|
+
const ascii = basename
|
|
41
|
+
.replace(/[^\x20-\x7e]/g, "_")
|
|
42
|
+
.replace(/["\\]/g, "_")
|
|
43
|
+
.slice(0, 180);
|
|
44
|
+
return ascii || "download";
|
|
45
|
+
}
|
|
46
|
+
export function versionFileContentDisposition(disposition, filePath) {
|
|
47
|
+
return `${disposition}; filename="${dispositionFilename(filePath)}"`;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A download remains inert even if a user agent ignores attachment handling:
|
|
51
|
+
* the CSP sandbox gives it an opaque origin and permits no script or fetch.
|
|
52
|
+
*/
|
|
53
|
+
export function versionFileAttachmentHeaders(filePath) {
|
|
54
|
+
return {
|
|
55
|
+
"content-disposition": versionFileContentDisposition("attachment", filePath),
|
|
56
|
+
"content-security-policy": "default-src 'none'; sandbox; frame-ancestors 'none'",
|
|
57
|
+
"x-content-type-options": "nosniff",
|
|
58
|
+
};
|
|
59
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spacefast/common",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Shared TypeScript contracts and utilities for Spacefast packages.",
|
|
6
6
|
"repository": {
|
|
@@ -20,6 +20,22 @@
|
|
|
20
20
|
"brand-assets",
|
|
21
21
|
"dist"
|
|
22
22
|
],
|
|
23
|
+
"spacefastTestCache": {
|
|
24
|
+
"mode": "hermetic",
|
|
25
|
+
"inputs": [
|
|
26
|
+
"../../apps/www/dist/.well-known/agent-card.json",
|
|
27
|
+
"../../apps/www/dist/ai.txt",
|
|
28
|
+
"../../apps/www/dist/llms-full.txt",
|
|
29
|
+
"../../apps/www/dist/llms.txt",
|
|
30
|
+
"../../apps/www/public/skill-references.md",
|
|
31
|
+
"../../apps/www/public/skill.md",
|
|
32
|
+
"../../e2e-tests/fixtures/zero-all-features/api-finalize-request.json",
|
|
33
|
+
"../../e2e-tests/fixtures/zero-all-features/runtime-compiler-finalize-input.json",
|
|
34
|
+
"../../runtime/engine/shared/fonts",
|
|
35
|
+
"../cli/SKILL.md",
|
|
36
|
+
"../cli/references.md"
|
|
37
|
+
]
|
|
38
|
+
},
|
|
23
39
|
"exports": {
|
|
24
40
|
"./brand": {
|
|
25
41
|
"types": "./dist/brand.d.ts",
|
|
@@ -93,6 +109,9 @@
|
|
|
93
109
|
"dependencies": {
|
|
94
110
|
"@tanstack/react-query": "^5.101.4",
|
|
95
111
|
"culori": "^4.0.2",
|
|
112
|
+
"js-yaml": "^4.1.1",
|
|
113
|
+
"mime": "^4.1.0",
|
|
114
|
+
"parse5": "^7.3.0",
|
|
96
115
|
"smol-toml": "^1.7.0",
|
|
97
116
|
"zod": "^4.4.3"
|
|
98
117
|
}
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
export declare function normalizeMountPathPrefix(value: string): string;
|
|
3
|
-
export declare const mountPathPrefixSchema: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
4
|
-
export declare const spaceMountCreateSchema: z.ZodObject<{
|
|
5
|
-
sourceVersionId: z.ZodCustom<`ver_${string}`, `ver_${string}`>;
|
|
6
|
-
pathPrefix: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
7
|
-
targetSpaceId: z.ZodCustom<`spc_${string}`, `spc_${string}`>;
|
|
8
|
-
channel: z.ZodDefault<z.ZodLiteral<"live">>;
|
|
9
|
-
}, z.core.$strip>;
|
|
10
|
-
export declare const spaceMountSchema: z.ZodObject<{
|
|
11
|
-
id: z.ZodCustom<`mnt_${string}`, `mnt_${string}`>;
|
|
12
|
-
spaceId: z.ZodCustom<`spc_${string}`, `spc_${string}`>;
|
|
13
|
-
sourceVersionId: z.ZodCustom<`ver_${string}`, `ver_${string}`>;
|
|
14
|
-
pathPrefix: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
15
|
-
targetSpaceId: z.ZodCustom<`spc_${string}`, `spc_${string}`>;
|
|
16
|
-
targetSpaceSlug: z.ZodString;
|
|
17
|
-
channel: z.ZodLiteral<"live">;
|
|
18
|
-
versionId: z.ZodNullable<z.ZodCustom<`ver_${string}`, `ver_${string}`>>;
|
|
19
|
-
targetVersionId: z.ZodNullable<z.ZodCustom<`ver_${string}`, `ver_${string}`>>;
|
|
20
|
-
createdAt: z.ZodString;
|
|
21
|
-
updatedAt: z.ZodString;
|
|
22
|
-
}, z.core.$strip>;
|
|
23
|
-
export declare const spaceMountListResponseSchema: z.ZodObject<{
|
|
24
|
-
data: z.ZodArray<z.ZodObject<{
|
|
25
|
-
id: z.ZodCustom<`mnt_${string}`, `mnt_${string}`>;
|
|
26
|
-
spaceId: z.ZodCustom<`spc_${string}`, `spc_${string}`>;
|
|
27
|
-
sourceVersionId: z.ZodCustom<`ver_${string}`, `ver_${string}`>;
|
|
28
|
-
pathPrefix: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
29
|
-
targetSpaceId: z.ZodCustom<`spc_${string}`, `spc_${string}`>;
|
|
30
|
-
targetSpaceSlug: z.ZodString;
|
|
31
|
-
channel: z.ZodLiteral<"live">;
|
|
32
|
-
versionId: z.ZodNullable<z.ZodCustom<`ver_${string}`, `ver_${string}`>>;
|
|
33
|
-
targetVersionId: z.ZodNullable<z.ZodCustom<`ver_${string}`, `ver_${string}`>>;
|
|
34
|
-
createdAt: z.ZodString;
|
|
35
|
-
updatedAt: z.ZodString;
|
|
36
|
-
}, z.core.$strip>>;
|
|
37
|
-
}, z.core.$strip>;
|
|
38
|
-
export declare const spaceMountResponseSchema: z.ZodObject<{
|
|
39
|
-
data: z.ZodObject<{
|
|
40
|
-
id: z.ZodCustom<`mnt_${string}`, `mnt_${string}`>;
|
|
41
|
-
spaceId: z.ZodCustom<`spc_${string}`, `spc_${string}`>;
|
|
42
|
-
sourceVersionId: z.ZodCustom<`ver_${string}`, `ver_${string}`>;
|
|
43
|
-
pathPrefix: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
44
|
-
targetSpaceId: z.ZodCustom<`spc_${string}`, `spc_${string}`>;
|
|
45
|
-
targetSpaceSlug: z.ZodString;
|
|
46
|
-
channel: z.ZodLiteral<"live">;
|
|
47
|
-
versionId: z.ZodNullable<z.ZodCustom<`ver_${string}`, `ver_${string}`>>;
|
|
48
|
-
targetVersionId: z.ZodNullable<z.ZodCustom<`ver_${string}`, `ver_${string}`>>;
|
|
49
|
-
createdAt: z.ZodString;
|
|
50
|
-
updatedAt: z.ZodString;
|
|
51
|
-
}, z.core.$strip>;
|
|
52
|
-
operation: z.ZodNullable<z.ZodObject<{
|
|
53
|
-
id: z.ZodString;
|
|
54
|
-
kind: z.ZodString;
|
|
55
|
-
status: z.ZodEnum<{
|
|
56
|
-
failed: "failed";
|
|
57
|
-
canceled: "canceled";
|
|
58
|
-
queued: "queued";
|
|
59
|
-
running: "running";
|
|
60
|
-
succeeded: "succeeded";
|
|
61
|
-
}>;
|
|
62
|
-
resources: z.ZodArray<z.ZodObject<{
|
|
63
|
-
type: z.ZodString;
|
|
64
|
-
id: z.ZodString;
|
|
65
|
-
}, z.core.$strip>>;
|
|
66
|
-
progress: z.ZodOptional<z.ZodObject<{
|
|
67
|
-
total: z.ZodNumber;
|
|
68
|
-
completed: z.ZodNumber;
|
|
69
|
-
failed: z.ZodNumber;
|
|
70
|
-
}, z.core.$strip>>;
|
|
71
|
-
diagnostics: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
72
|
-
code: z.ZodString;
|
|
73
|
-
severity: z.ZodEnum<{
|
|
74
|
-
info: "info";
|
|
75
|
-
error: "error";
|
|
76
|
-
warning: "warning";
|
|
77
|
-
}>;
|
|
78
|
-
message: z.ZodString;
|
|
79
|
-
path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
80
|
-
provider: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
81
|
-
registrar: "registrar";
|
|
82
|
-
wpcloud: "wpcloud";
|
|
83
|
-
dns: "dns";
|
|
84
|
-
runtime: "runtime";
|
|
85
|
-
}>>>;
|
|
86
|
-
details: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
87
|
-
fix: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
88
|
-
retryable: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
89
|
-
}, z.core.$strip>>>;
|
|
90
|
-
createdAt: z.ZodString;
|
|
91
|
-
finishedAt: z.ZodOptional<z.ZodString>;
|
|
92
|
-
}, z.core.$strip>>;
|
|
93
|
-
}, z.core.$strip>;
|
|
94
|
-
export declare const spaceMountDeleteResponseSchema: z.ZodObject<{
|
|
95
|
-
data: z.ZodObject<{
|
|
96
|
-
id: z.ZodCustom<`mnt_${string}`, `mnt_${string}`>;
|
|
97
|
-
deleted: z.ZodLiteral<true>;
|
|
98
|
-
}, z.core.$strip>;
|
|
99
|
-
operation: z.ZodNullable<z.ZodObject<{
|
|
100
|
-
id: z.ZodString;
|
|
101
|
-
kind: z.ZodString;
|
|
102
|
-
status: z.ZodEnum<{
|
|
103
|
-
failed: "failed";
|
|
104
|
-
canceled: "canceled";
|
|
105
|
-
queued: "queued";
|
|
106
|
-
running: "running";
|
|
107
|
-
succeeded: "succeeded";
|
|
108
|
-
}>;
|
|
109
|
-
resources: z.ZodArray<z.ZodObject<{
|
|
110
|
-
type: z.ZodString;
|
|
111
|
-
id: z.ZodString;
|
|
112
|
-
}, z.core.$strip>>;
|
|
113
|
-
progress: z.ZodOptional<z.ZodObject<{
|
|
114
|
-
total: z.ZodNumber;
|
|
115
|
-
completed: z.ZodNumber;
|
|
116
|
-
failed: z.ZodNumber;
|
|
117
|
-
}, z.core.$strip>>;
|
|
118
|
-
diagnostics: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
119
|
-
code: z.ZodString;
|
|
120
|
-
severity: z.ZodEnum<{
|
|
121
|
-
info: "info";
|
|
122
|
-
error: "error";
|
|
123
|
-
warning: "warning";
|
|
124
|
-
}>;
|
|
125
|
-
message: z.ZodString;
|
|
126
|
-
path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
127
|
-
provider: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
128
|
-
registrar: "registrar";
|
|
129
|
-
wpcloud: "wpcloud";
|
|
130
|
-
dns: "dns";
|
|
131
|
-
runtime: "runtime";
|
|
132
|
-
}>>>;
|
|
133
|
-
details: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
134
|
-
fix: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
135
|
-
retryable: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
136
|
-
}, z.core.$strip>>>;
|
|
137
|
-
createdAt: z.ZodString;
|
|
138
|
-
finishedAt: z.ZodOptional<z.ZodString>;
|
|
139
|
-
}, z.core.$strip>>;
|
|
140
|
-
}, z.core.$strip>;
|
|
141
|
-
export type SpaceMountCreate = z.infer<typeof spaceMountCreateSchema>;
|
|
142
|
-
export type SpaceMount = z.infer<typeof spaceMountSchema>;
|
package/dist/contracts/mounts.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { dataEnvelope, mutationEnvelope } from "./common.js";
|
|
3
|
-
import { registeredIdSchema } from "./ids.js";
|
|
4
|
-
const RESERVED_MOUNT_PREFIXES = ["/__spacefast", "/__stattic", "/.well-known"];
|
|
5
|
-
export function normalizeMountPathPrefix(value) {
|
|
6
|
-
const trimmed = value.trim();
|
|
7
|
-
if (trimmed === "" || trimmed === "/")
|
|
8
|
-
return "/";
|
|
9
|
-
return `/${trimmed.replace(/^\/+|\/+$/g, "")}`;
|
|
10
|
-
}
|
|
11
|
-
export const mountPathPrefixSchema = z
|
|
12
|
-
.string()
|
|
13
|
-
.min(1)
|
|
14
|
-
.max(1024)
|
|
15
|
-
.transform(normalizeMountPathPrefix)
|
|
16
|
-
.refine((value) => value !== "/", "A mount path must be below the site root.")
|
|
17
|
-
.refine((value) => Array.from(value).every((character) => {
|
|
18
|
-
const codePoint = character.codePointAt(0) ?? 0;
|
|
19
|
-
return codePoint > 0x9f || (codePoint > 0x1f && codePoint !== 0x7f);
|
|
20
|
-
}), "Mount path is invalid.")
|
|
21
|
-
.refine((value) => !value.includes("\\") && !value.includes("//"), "Mount path is invalid.")
|
|
22
|
-
.refine((value) => !value
|
|
23
|
-
.split("/")
|
|
24
|
-
.filter(Boolean)
|
|
25
|
-
.some((segment) => segment === "." || segment === ".."), "Mount path is invalid.")
|
|
26
|
-
.refine((value) => !RESERVED_MOUNT_PREFIXES.some((reserved) => value === reserved || value.startsWith(`${reserved}/`)), "Mount path uses a Spacefast-reserved prefix.")
|
|
27
|
-
.describe("Normalized path prefix on the website, for example `/docs`.");
|
|
28
|
-
export const spaceMountCreateSchema = z.object({
|
|
29
|
-
sourceVersionId: registeredIdSchema("ver").describe("Immutable website version whose production activation enables this mount."),
|
|
30
|
-
pathPrefix: mountPathPrefixSchema,
|
|
31
|
-
targetSpaceId: registeredIdSchema("spc").describe("Explicitly authorized same-team space to mount."),
|
|
32
|
-
channel: z
|
|
33
|
-
.literal("live")
|
|
34
|
-
.default("live")
|
|
35
|
-
.describe("Target production channel followed by this mount."),
|
|
36
|
-
});
|
|
37
|
-
export const spaceMountSchema = z.object({
|
|
38
|
-
id: registeredIdSchema("mnt"),
|
|
39
|
-
spaceId: registeredIdSchema("spc"),
|
|
40
|
-
sourceVersionId: registeredIdSchema("ver"),
|
|
41
|
-
pathPrefix: mountPathPrefixSchema,
|
|
42
|
-
targetSpaceId: registeredIdSchema("spc"),
|
|
43
|
-
targetSpaceSlug: z.string(),
|
|
44
|
-
channel: z.literal("live"),
|
|
45
|
-
versionId: registeredIdSchema("ver")
|
|
46
|
-
.nullable()
|
|
47
|
-
.describe("Immutable target version currently serving from the mount."),
|
|
48
|
-
targetVersionId: registeredIdSchema("ver")
|
|
49
|
-
.nullable()
|
|
50
|
-
.describe("Target production-channel version the durable synchronizer is converging toward."),
|
|
51
|
-
createdAt: z.string().datetime(),
|
|
52
|
-
updatedAt: z.string().datetime(),
|
|
53
|
-
});
|
|
54
|
-
export const spaceMountListResponseSchema = dataEnvelope(z.array(spaceMountSchema));
|
|
55
|
-
export const spaceMountResponseSchema = mutationEnvelope(spaceMountSchema);
|
|
56
|
-
export const spaceMountDeleteResponseSchema = mutationEnvelope(z.object({ id: registeredIdSchema("mnt"), deleted: z.literal(true) }));
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { RuntimeRule } from "../contracts/access.js";
|
|
2
|
-
export declare const ACCESS_GRANT_GATE_RULE_ID = "access-grant-gate";
|
|
3
|
-
export declare const ACCESS_GRANT_ADMISSION_RULE_ID = "access-grant-admission";
|
|
4
|
-
export type AccessGrantExposure = {
|
|
5
|
-
anonymousAccess: "gated" | "gated_with_exceptions" | "partly_public" | "shadowed";
|
|
6
|
-
earlierAnonymousAllowRules: number;
|
|
7
|
-
earlierManagedAccessRules: number;
|
|
8
|
-
precedingTerminalRules: number;
|
|
9
|
-
};
|
|
10
|
-
export declare function withAccessGrantGate(rules: RuntimeRule[], grant: string): RuntimeRule[];
|
|
11
|
-
export declare function withoutAccessGrantRule(rules: RuntimeRule[], selectedIndex: number): RuntimeRule[];
|
|
12
|
-
export declare function isAccessGrantAdmissionRule(rule: RuntimeRule): boolean;
|
|
13
|
-
export declare function isAccessGrantFallbackRule(rule: RuntimeRule): boolean;
|
|
14
|
-
export declare function accessGrantExposure(rules: RuntimeRule[]): AccessGrantExposure;
|