@spacefast/common 0.0.11 → 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/agents/connect-targets.d.ts +4 -4
- package/dist/agents/connect-targets.js +3 -3
- package/dist/agents/private-key-oauth.d.ts +37 -0
- package/dist/agents/private-key-oauth.js +158 -0
- package/dist/config/domains.js +1 -1
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.js +1 -0
- package/dist/config/postgres-budget.d.ts +126 -0
- package/dist/config/postgres-budget.js +135 -0
- package/dist/config/postgres-budget.json +50 -0
- package/dist/contracts/access.d.ts +386 -1183
- package/dist/contracts/access.js +240 -1018
- package/dist/contracts/activity.d.ts +1 -1
- package/dist/contracts/activity.js +11 -19
- package/dist/contracts/api-keys.d.ts +69 -45
- package/dist/contracts/api-keys.js +3 -0
- package/dist/contracts/archives.d.ts +9 -10
- package/dist/contracts/archives.js +4 -6
- package/dist/contracts/builds.d.ts +8 -8
- package/dist/contracts/builds.js +28 -48
- package/dist/contracts/channels.js +1 -2
- package/dist/contracts/comments.d.ts +102 -93
- package/dist/contracts/comments.js +121 -63
- package/dist/contracts/common.d.ts +4 -3
- package/dist/contracts/common.js +2 -0
- 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/deployments.d.ts +3 -3
- package/dist/contracts/device-auth.d.ts +21 -15
- package/dist/contracts/docs.d.ts +5 -5
- package/dist/contracts/domains.d.ts +261 -1330
- package/dist/contracts/domains.js +39 -301
- package/dist/contracts/email-preferences.d.ts +50 -0
- package/dist/contracts/email-preferences.js +44 -0
- package/dist/contracts/enums.d.ts +3 -5
- package/dist/contracts/enums.js +3 -8
- package/dist/contracts/error-code-meta.d.ts +99 -33
- package/dist/contracts/error-code-meta.js +36 -9
- package/dist/contracts/error-codes.d.ts +1 -1
- package/dist/contracts/error-codes.js +28 -11
- package/dist/contracts/execution.d.ts +212 -0
- package/dist/contracts/execution.js +288 -0
- package/dist/contracts/feature-lifecycle.d.ts +498 -2
- package/dist/contracts/feature-lifecycle.js +539 -2
- package/dist/contracts/features.d.ts +184 -74
- package/dist/contracts/features.js +4 -303
- 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 +6 -5
- package/dist/contracts/ids.js +6 -5
- package/dist/contracts/internal.d.ts +3 -3
- package/dist/contracts/mcp.d.ts +12 -12
- package/dist/contracts/me.js +1 -1
- package/dist/contracts/mounts.d.ts +142 -0
- package/dist/contracts/mounts.js +56 -0
- package/dist/contracts/oauth-resources.d.ts +5 -5
- package/dist/contracts/oauth-resources.js +2 -0
- package/dist/contracts/operations.d.ts +4 -4
- package/dist/contracts/pages.d.ts +6 -14
- package/dist/contracts/pages.js +11 -23
- package/dist/contracts/plan-policy.d.ts +2 -9
- package/dist/contracts/plan-policy.js +1 -4
- package/dist/contracts/platform.d.ts +80 -32
- 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 +21 -85
- package/dist/contracts/resources.js +17 -47
- package/dist/contracts/runtime-api.d.ts +799 -192
- package/dist/contracts/runtime-api.js +231 -100
- 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/sf-config-v1.js +1 -1
- package/dist/contracts/sites.d.ts +17 -12
- package/dist/contracts/sites.js +30 -12
- package/dist/contracts/space-config.d.ts +46 -117
- package/dist/contracts/space-config.js +323 -25
- package/dist/contracts/spaces.d.ts +392 -256
- package/dist/contracts/spaces.js +163 -83
- package/dist/contracts/superadmin-emails.d.ts +27 -3
- package/dist/contracts/superadmin-emails.js +10 -15
- package/dist/contracts/superadmin-runtime.d.ts +2 -2
- package/dist/contracts/superadmin-spaces.d.ts +19 -142
- package/dist/contracts/superadmin-spaces.js +7 -0
- package/dist/contracts/tags.d.ts +66 -36
- package/dist/contracts/tags.js +195 -11
- package/dist/contracts/teams.d.ts +9 -9
- package/dist/contracts/transfers.d.ts +1 -2
- package/dist/contracts/variables.d.ts +4 -4
- package/dist/contracts/variables.js +4 -3
- package/dist/contracts/webhooks.d.ts +2 -2
- package/dist/contracts/zero.d.ts +437 -193
- package/dist/contracts/zero.js +149 -158
- package/dist/dashboard-paths/index.d.ts +3 -3
- package/dist/dashboard-paths/index.js +1 -0
- package/dist/docs/agent-prose.js +10 -8
- package/dist/docs/agent-setup.d.ts +6 -4
- package/dist/docs/agent-setup.js +26 -16
- package/dist/docs/agent-solutions.js +1 -1
- package/dist/docs/catalog.d.ts +35 -37
- package/dist/docs/catalog.js +36 -38
- package/dist/docs/error-docs.js +108 -44
- 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/dns-instructions.d.ts +29 -0
- package/dist/utils/dns-instructions.js +78 -0
- package/dist/utils/domain-diagnostics.d.ts +29 -0
- package/dist/utils/domain-diagnostics.js +63 -0
- package/dist/utils/egress-policy.fixtures.json +51 -0
- package/dist/utils/grants.d.ts +53 -0
- package/dist/utils/grants.js +160 -0
- package/dist/utils/id-hints.d.ts +1 -0
- package/dist/utils/id-hints.js +55 -13
- package/dist/utils/local-space-state.js +1 -0
- package/dist/utils/page-colors.d.ts +50 -0
- package/dist/utils/page-colors.js +167 -0
- package/dist/utils/page-fonts.d.ts +2 -0
- package/dist/utils/page-fonts.js +4 -0
- package/dist/utils/pages.d.ts +19 -6
- package/dist/utils/pages.js +122 -49
- package/dist/utils/production-runtime.d.ts +18 -0
- package/dist/utils/production-runtime.js +28 -0
- package/dist/utils/publish-policy.d.ts +34 -4
- package/dist/utils/publish-policy.js +132 -61
- package/dist/utils/query-keys.d.ts +7 -13
- package/dist/utils/query-keys.js +12 -18
- package/dist/utils/source-archive-policy.d.ts +2 -0
- package/dist/utils/source-archive-policy.js +2 -0
- 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.fixtures.json +57 -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 +6 -4
- package/dist/contracts/annotations.d.ts +0 -327
- package/dist/contracts/annotations.js +0 -235
- package/dist/contracts/generated-feature-launch-entries.d.ts +0 -2
- package/dist/contracts/generated-feature-launch-entries.js +0 -518
- package/dist/contracts/publishes.d.ts +0 -135
- package/dist/contracts/publishes.js +0 -162
- package/dist/utils/access-match.d.ts +0 -39
- package/dist/utils/access-match.js +0 -296
- package/dist/utils/sf-config-v1.d.ts +0 -2
- package/dist/utils/sf-config-v1.js +0 -542
|
@@ -21,7 +21,6 @@ export declare const qk: {
|
|
|
21
21
|
teamSpaces: (id: string) => readonly ["teams", string, "spaces"];
|
|
22
22
|
teamDomains: (id: string) => readonly ["teams", string, "domains"];
|
|
23
23
|
teamManagedDomains: (id: string) => readonly ["teams", string, "managed-domains"];
|
|
24
|
-
domainBindings: () => readonly ["domain-bindings"];
|
|
25
24
|
slugAvailability: (kind: "team" | "space", slug: string, teamId?: string, currentSlug?: string) => readonly ["slugs", "availability", "space" | "team", string, string, string];
|
|
26
25
|
teamVariables: (id: string) => readonly ["teams", string, "variables"];
|
|
27
26
|
teamActivity: (id: string, limit: number) => readonly ["teams", string, "activity", number];
|
|
@@ -30,8 +29,8 @@ export declare const qk: {
|
|
|
30
29
|
spaceVersions: (id: string) => readonly ["spaces", string, "versions"];
|
|
31
30
|
spaceVersionsHistory: (id: string) => readonly ["spaces", string, "versions", "history"];
|
|
32
31
|
spaceCollaboration: (id: string) => readonly ["spaces", string, "collaboration"];
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
spaceComments: (id: string) => readonly ["spaces", string, "comments"];
|
|
33
|
+
spaceCommentThread: (id: string, threadId: string) => readonly ["spaces", string, "comments", string];
|
|
35
34
|
spaceActivity: (id: string, limit: number) => readonly ["spaces", string, "activity", number];
|
|
36
35
|
spaceDeployments: (id: string) => readonly ["spaces", string, "deployments"];
|
|
37
36
|
spaceTags: (id: string) => readonly ["spaces", string, "tags"];
|
|
@@ -39,11 +38,11 @@ export declare const qk: {
|
|
|
39
38
|
spaceTagDiff: (id: string, versionId: string) => readonly ["spaces", string, "tags", string, "diff"];
|
|
40
39
|
spaceTagReleases: (id: string) => readonly ["spaces", string, "tags", "releases"];
|
|
41
40
|
spaceTagsEffective: (id: string) => readonly ["spaces", string, "tags", "effective"];
|
|
42
|
-
build: (id: string) => readonly ["builds", string];
|
|
43
|
-
buildLogs: (id: string, limit?: number) => readonly ["builds", string, "logs"] | readonly ["builds", string, "logs", number];
|
|
41
|
+
build: (spaceId: string, id: string) => readonly ["spaces", string, "builds", string];
|
|
42
|
+
buildLogs: (spaceId: string, id: string, limit?: number) => readonly ["spaces", string, "builds", string, "logs"] | readonly ["spaces", string, "builds", string, "logs", number];
|
|
44
43
|
spaceBuilds: (id: string) => readonly ["spaces", string, "builds"];
|
|
45
44
|
spaceRepositoryConnection: (id: string, connectionType?: string) => readonly ["spaces", string, "repository-connection", string];
|
|
46
|
-
repositoryInstallations: (spaceId: string) => readonly ["
|
|
45
|
+
repositoryInstallations: (spaceId: string) => readonly ["spaces", string, "repository-installations"];
|
|
47
46
|
repositoryInstallationRepositories: (installationId: string) => readonly ["repository-connections", "installations", string, "repositories"];
|
|
48
47
|
spaceRepositoryAnalyze: (id: string, connectionType?: string, ref?: string, root?: string) => readonly ["spaces", string, "repository-connection", string, "analyze", string, string];
|
|
49
48
|
spaceRepositoryWebhookDeliveries: (id: string, connectionType?: string) => readonly ["spaces", string, "repository-webhook-deliveries", string];
|
|
@@ -51,7 +50,7 @@ export declare const qk: {
|
|
|
51
50
|
webhook: (webhookId: string) => readonly ["webhooks", string];
|
|
52
51
|
webhookDeliveries: (webhookId: string) => readonly ["webhooks", string, "deliveries"];
|
|
53
52
|
spaceVersion: (id: string, versionId: string) => readonly ["spaces", string, "versions", string];
|
|
54
|
-
|
|
53
|
+
spaceVersionComments: (id: string, versionId: string, status?: string) => readonly ["spaces", string, "versions", string, "comments"] | readonly ["spaces", string, "versions", string, "comments", string];
|
|
55
54
|
spaceVersionFiles: (id: string, versionId: string) => readonly ["spaces", string, "versions", string, "files"];
|
|
56
55
|
spaceVersionFile: (id: string, versionId: string, path: string) => readonly ["spaces", string, "versions", string, "files", string];
|
|
57
56
|
spaceVersionFileDirectUrl: (id: string, versionId: string, path: string) => readonly ["spaces", string, "versions", string, "files", string, "direct-url"];
|
|
@@ -64,20 +63,15 @@ export declare const qk: {
|
|
|
64
63
|
spaceDomains: (id: string) => readonly ["spaces", string, "domains"];
|
|
65
64
|
spaceRuntimeStatus: (id: string) => readonly ["spaces", string, "runtime"];
|
|
66
65
|
spaceApplyState: (id: string) => readonly ["spaces", string, "apply-state"];
|
|
67
|
-
spaceZero: (id: string) => readonly ["spaces", string, "zero"];
|
|
68
66
|
spaceZeroDb: (id: string) => readonly ["spaces", string, "zero", "db"];
|
|
69
|
-
|
|
67
|
+
spaceRuntimeLogs: (id: string, limit: number) => readonly ["spaces", string, "logs", "runtime", number];
|
|
70
68
|
spaceZeroRealtimeEvents: (id: string, limit: number) => readonly ["spaces", string, "zero", "realtime", "events", number];
|
|
71
69
|
spaceVariables: (id: string) => readonly ["spaces", string, "variables"];
|
|
72
70
|
spaceCertificates: (id: string) => readonly ["spaces", string, "runtime", "certificates"];
|
|
73
71
|
spaceLogs: (id: string, kind: "build" | "access" | "runtime") => readonly ["spaces", string, "logs", "build" | "runtime" | "access"];
|
|
74
72
|
spaceAnalytics: (id: string, window: string) => readonly ["spaces", string, "analytics", string];
|
|
75
|
-
spaceFirewall: (id: string) => readonly ["spaces", string, "access", "firewall"];
|
|
76
|
-
spaceAccessViews: (id: string, since?: string) => readonly ["spaces", string, "access", "views", string];
|
|
77
|
-
teamServiceTokens: (teamId: string) => readonly ["teams", string, "access", "service-tokens"];
|
|
78
73
|
teamAgentHandoffs: (teamId: string) => readonly ["teams", string, "agent-handoffs"];
|
|
79
74
|
teamAccessDefaults: (teamId: string) => readonly ["teams", string, "access", "defaults"];
|
|
80
|
-
teamAccessConnections: (teamId: string) => readonly ["teams", string, "access", "connections"];
|
|
81
75
|
domain: (teamId: string, ref: string) => readonly ["teams", string, "domains", string];
|
|
82
76
|
domainDiagnostics: (teamId: string, domainId: string) => readonly ["teams", string, "domains", string, "diagnostics"];
|
|
83
77
|
domainDnsCapabilities: (domainId: string) => readonly ["domains", string, "dns", "capabilities"];
|
package/dist/utils/query-keys.js
CHANGED
|
@@ -26,7 +26,6 @@ export const qk = {
|
|
|
26
26
|
teamSpaces: (id) => ["teams", id, "spaces"],
|
|
27
27
|
teamDomains: (id) => ["teams", id, "domains"],
|
|
28
28
|
teamManagedDomains: (id) => ["teams", id, "managed-domains"],
|
|
29
|
-
domainBindings: () => ["domain-bindings"],
|
|
30
29
|
slugAvailability: (kind, slug, teamId, currentSlug) => ["slugs", "availability", kind, slug, teamId ?? "", currentSlug ?? ""],
|
|
31
30
|
teamVariables: (id) => ["teams", id, "variables"],
|
|
32
31
|
teamActivity: (id, limit) => ["teams", id, "activity", limit],
|
|
@@ -38,8 +37,8 @@ export const qk = {
|
|
|
38
37
|
// `invalidateQueries({ queryKey: qk.spaceVersions(id) })` still reaches it.
|
|
39
38
|
spaceVersionsHistory: (id) => [...qk.spaceVersions(id), "history"],
|
|
40
39
|
spaceCollaboration: (id) => ["spaces", id, "collaboration"],
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
spaceComments: (id) => ["spaces", id, "comments"],
|
|
41
|
+
spaceCommentThread: (id, threadId) => [...qk.spaceComments(id), threadId],
|
|
43
42
|
spaceActivity: (id, limit) => ["spaces", id, "activity", limit],
|
|
44
43
|
spaceDeployments: (id) => ["spaces", id, "deployments"],
|
|
45
44
|
spaceTags: (id) => ["spaces", id, "tags"],
|
|
@@ -49,15 +48,15 @@ export const qk = {
|
|
|
49
48
|
// The merged (system+team+space) read-only view; never a write base — see
|
|
50
49
|
// `fetchSpaceReleasedGraph` in apps/my/src/lib/space-queries.ts.
|
|
51
50
|
spaceTagsEffective: (id) => ["spaces", id, "tags", "effective"],
|
|
52
|
-
build: (id) => [
|
|
51
|
+
build: (spaceId, id) => [...qk.spaceBuilds(spaceId), id],
|
|
53
52
|
// Observers with different limits must not share a cache entry; calling with
|
|
54
53
|
// no limit yields the bare prefix for invalidating every limit at once.
|
|
55
|
-
buildLogs: (id, limit) => limit === undefined
|
|
56
|
-
? [
|
|
57
|
-
: [
|
|
54
|
+
buildLogs: (spaceId, id, limit) => limit === undefined
|
|
55
|
+
? [...qk.build(spaceId, id), "logs"]
|
|
56
|
+
: [...qk.build(spaceId, id), "logs", limit],
|
|
58
57
|
spaceBuilds: (id) => ["spaces", id, "builds"],
|
|
59
58
|
spaceRepositoryConnection: (id, connectionType = "connected") => ["spaces", id, "repository-connection", connectionType],
|
|
60
|
-
repositoryInstallations: (spaceId) => ["repository-
|
|
59
|
+
repositoryInstallations: (spaceId) => [...qk.space(spaceId), "repository-installations"],
|
|
61
60
|
repositoryInstallationRepositories: (installationId) => ["repository-connections", "installations", installationId, "repositories"],
|
|
62
61
|
spaceRepositoryAnalyze: (id, connectionType = "connected", ref = "", root = "") => ["spaces", id, "repository-connection", connectionType, "analyze", ref, root],
|
|
63
62
|
spaceRepositoryWebhookDeliveries: (id, connectionType = "connected") => ["spaces", id, "repository-webhook-deliveries", connectionType],
|
|
@@ -66,10 +65,10 @@ export const qk = {
|
|
|
66
65
|
webhookDeliveries: (webhookId) => ["webhooks", webhookId, "deliveries"],
|
|
67
66
|
spaceVersion: (id, versionId) => ["spaces", id, "versions", versionId],
|
|
68
67
|
// Calling with no status yields the bare prefix, for invalidating every
|
|
69
|
-
// status-scoped
|
|
70
|
-
|
|
71
|
-
? ["spaces", id, "versions", versionId, "
|
|
72
|
-
: ["spaces", id, "versions", versionId, "
|
|
68
|
+
// status-scoped version comment list at once.
|
|
69
|
+
spaceVersionComments: (id, versionId, status) => status === undefined
|
|
70
|
+
? ["spaces", id, "versions", versionId, "comments"]
|
|
71
|
+
: ["spaces", id, "versions", versionId, "comments", status],
|
|
73
72
|
spaceVersionFiles: (id, versionId) => ["spaces", id, "versions", versionId, "files"],
|
|
74
73
|
spaceVersionFile: (id, versionId, path) => ["spaces", id, "versions", versionId, "files", path],
|
|
75
74
|
spaceVersionFileDirectUrl: (id, versionId, path) => ["spaces", id, "versions", versionId, "files", path, "direct-url"],
|
|
@@ -82,20 +81,15 @@ export const qk = {
|
|
|
82
81
|
spaceDomains: (id) => ["spaces", id, "domains"],
|
|
83
82
|
spaceRuntimeStatus: (id) => ["spaces", id, "runtime"],
|
|
84
83
|
spaceApplyState: (id) => ["spaces", id, "apply-state"],
|
|
85
|
-
spaceZero: (id) => ["spaces", id, "zero"],
|
|
86
84
|
spaceZeroDb: (id) => ["spaces", id, "zero", "db"],
|
|
87
|
-
|
|
85
|
+
spaceRuntimeLogs: (id, limit) => ["spaces", id, "logs", "runtime", limit],
|
|
88
86
|
spaceZeroRealtimeEvents: (id, limit) => ["spaces", id, "zero", "realtime", "events", limit],
|
|
89
87
|
spaceVariables: (id) => ["spaces", id, "variables"],
|
|
90
88
|
spaceCertificates: (id) => ["spaces", id, "runtime", "certificates"],
|
|
91
89
|
spaceLogs: (id, kind) => ["spaces", id, "logs", kind],
|
|
92
90
|
spaceAnalytics: (id, window) => ["spaces", id, "analytics", window],
|
|
93
|
-
spaceFirewall: (id) => ["spaces", id, "access", "firewall"],
|
|
94
|
-
spaceAccessViews: (id, since) => ["spaces", id, "access", "views", since ?? ""],
|
|
95
|
-
teamServiceTokens: (teamId) => ["teams", teamId, "access", "service-tokens"],
|
|
96
91
|
teamAgentHandoffs: (teamId) => ["teams", teamId, "agent-handoffs"],
|
|
97
92
|
teamAccessDefaults: (teamId) => ["teams", teamId, "access", "defaults"],
|
|
98
|
-
teamAccessConnections: (teamId) => ["teams", teamId, "access", "connections"],
|
|
99
93
|
domain: (teamId, ref) => ["teams", teamId, "domains", ref],
|
|
100
94
|
domainDiagnostics: (teamId, domainId) => ["teams", teamId, "domains", domainId, "diagnostics"],
|
|
101
95
|
domainDnsCapabilities: (domainId) => ["domains", domainId, "dns", "capabilities"],
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Grant } from "../contracts/grants.js";
|
|
1
2
|
import { type SpaceConfig, type SpaceConfigFile } from "../contracts/space-config.js";
|
|
2
3
|
export type SpaceConfigBlockingIssueCode = "config_file_too_large" | "config_templates_over_limit" | "config_meta_too_long" | "config_invalid" | "inject_snippet_too_large" | "inject_invalid";
|
|
3
4
|
export type SpaceConfigIssue = {
|
|
@@ -8,6 +9,9 @@ export type SpaceConfigIssue = {
|
|
|
8
9
|
path?: string;
|
|
9
10
|
details?: Record<string, unknown>;
|
|
10
11
|
};
|
|
12
|
+
export declare const CONFIG_PUBLIC_GRANT_COMPILED_ID = "config:access.public";
|
|
13
|
+
/** Compiles the file-only access declaration; activation decides which Version is live. */
|
|
14
|
+
export declare function compileSpaceConfigPublicGrant(fileConfig: Pick<SpaceConfigFile, "access"> | null | undefined): Grant | null;
|
|
11
15
|
type SpaceConfigBlockingIssue = SpaceConfigIssue & {
|
|
12
16
|
code: SpaceConfigBlockingIssueCode;
|
|
13
17
|
};
|
|
@@ -16,7 +20,7 @@ type SpaceConfigBlockingIssue = SpaceConfigIssue & {
|
|
|
16
20
|
* `config`): the 16 KB compiled-overlay cap plus the shared shape caps.
|
|
17
21
|
* Returns the first blocking issue, or null when the overlay is acceptable.
|
|
18
22
|
*/
|
|
19
|
-
export declare function spaceConfigOverlayIssue(config: SpaceConfig): SpaceConfigBlockingIssue | null;
|
|
23
|
+
export declare function spaceConfigOverlayIssue(config: SpaceConfig | Record<string, unknown>): SpaceConfigBlockingIssue | null;
|
|
20
24
|
export declare function stripJsonComments(raw: string): string;
|
|
21
25
|
export type ParsedSpaceConfigFile = {
|
|
22
26
|
/** Parsed config (cap- and shape-valid keys only); null when unusable. */
|
|
@@ -1,8 +1,35 @@
|
|
|
1
|
+
import { CONFIG_PUBLIC_GRANT_SOURCE_REFERENCE, grantSchema, } from "../contracts/grants.js";
|
|
1
2
|
import { SPACE_CONFIG_CAPS, SPACE_CONFIG_CANONICAL_FILE, SPACE_CONFIG_PRIVATE_FILES, spaceConfigFileSchema, spaceConfigSchema, } from "../contracts/space-config.js";
|
|
2
3
|
const TEXT_BYTES = new TextEncoder();
|
|
4
|
+
export const CONFIG_PUBLIC_GRANT_COMPILED_ID = "config:access.public";
|
|
3
5
|
function byteLength(value) {
|
|
4
6
|
return TEXT_BYTES.encode(value).length;
|
|
5
7
|
}
|
|
8
|
+
/** Compiles the file-only access declaration; activation decides which Version is live. */
|
|
9
|
+
export function compileSpaceConfigPublicGrant(fileConfig) {
|
|
10
|
+
const patterns = fileConfig?.access?.public ?? [];
|
|
11
|
+
const include = patterns.filter((pattern) => !pattern.startsWith("!"));
|
|
12
|
+
if (include.length === 0)
|
|
13
|
+
return null;
|
|
14
|
+
return grantSchema.parse({
|
|
15
|
+
id: CONFIG_PUBLIC_GRANT_COMPILED_ID,
|
|
16
|
+
name: "Public paths from sf.jsonc",
|
|
17
|
+
audience: { kind: "public" },
|
|
18
|
+
resources: {
|
|
19
|
+
include,
|
|
20
|
+
exclude: patterns
|
|
21
|
+
.filter((pattern) => pattern.startsWith("!"))
|
|
22
|
+
.map((pattern) => pattern.slice(1)),
|
|
23
|
+
},
|
|
24
|
+
capabilities: ["page.view"],
|
|
25
|
+
constraints: {},
|
|
26
|
+
target: { kind: "live" },
|
|
27
|
+
source: {
|
|
28
|
+
kind: "config",
|
|
29
|
+
reference: CONFIG_PUBLIC_GRANT_SOURCE_REFERENCE,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
}
|
|
6
33
|
function capIssues(candidate) {
|
|
7
34
|
const issues = [];
|
|
8
35
|
const templates = candidate.templates;
|
|
@@ -102,6 +129,14 @@ function capIssues(candidate) {
|
|
|
102
129
|
* Returns the first blocking issue, or null when the overlay is acceptable.
|
|
103
130
|
*/
|
|
104
131
|
export function spaceConfigOverlayIssue(config) {
|
|
132
|
+
if (Object.prototype.hasOwnProperty.call(config, "access")) {
|
|
133
|
+
return {
|
|
134
|
+
severity: "error",
|
|
135
|
+
code: "config_invalid",
|
|
136
|
+
message: "access is only valid in the committed sf.jsonc file.",
|
|
137
|
+
path: "access",
|
|
138
|
+
};
|
|
139
|
+
}
|
|
105
140
|
const encoded = JSON.stringify(config);
|
|
106
141
|
if (byteLength(encoded) > SPACE_CONFIG_CAPS.overlayBytes) {
|
|
107
142
|
return {
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export declare const PHP_LIKE_EXTENSIONS: string[];
|
|
2
|
+
export declare const INTERNAL_REDIRECT_RESPONSE_HEADERS: string[];
|
|
2
3
|
export declare const PLATFORM_MANAGED_RESPONSE_HEADERS: string[];
|
|
4
|
+
/** Reserved response-header namespaces owned by the platform's own serving signature. */
|
|
5
|
+
export declare const PLATFORM_MANAGED_RESPONSE_HEADER_PREFIXES: string[];
|
|
6
|
+
/** True when user rules may neither set nor remove this response header. */
|
|
7
|
+
export declare function isPlatformManagedResponseHeader(name: string): boolean;
|
|
3
8
|
export declare const NON_IMMUTABLE_EXTENSIONS: string[];
|
|
4
9
|
export declare const GUARANTEED_IMMUTABLE_PREFIXES: string[];
|
|
5
10
|
/** Lowercased extension without the leading dot, posix semantics. Dotfiles have no extension. */
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"phpLike": [
|
|
3
|
+
{ "path": "index.php", "expected": true },
|
|
4
|
+
{ "path": "nested/app.phtml", "expected": true },
|
|
5
|
+
{ "path": "lib.phar", "expected": true },
|
|
6
|
+
{ "path": "legacy.php5", "expected": true },
|
|
7
|
+
{ "path": "index.html", "expected": false },
|
|
8
|
+
{ "path": "assets/main.js", "expected": false },
|
|
9
|
+
{ "path": ".env", "expected": false }
|
|
10
|
+
],
|
|
11
|
+
"immutable": [
|
|
12
|
+
{ "path": "_next/static/chunks/main-app-4A_iFExJ.js", "expected": true },
|
|
13
|
+
{ "path": "_next/static/chunks/framework-2c1d4f8a.js", "expected": true },
|
|
14
|
+
{ "path": "_next/static/chunks/pages/index-a1b2c3d4e5f6.js", "expected": true },
|
|
15
|
+
{ "path": "_next/static/chunks/oton0Guf.js", "expected": true },
|
|
16
|
+
{ "path": "_next/static/css/app.plainname.css", "expected": true },
|
|
17
|
+
{ "path": "/_next/static/chunks/oton0Guf.js", "expected": true },
|
|
18
|
+
{ "path": "_app/immutable/entry/start.DYyuCeEr.js", "expected": true },
|
|
19
|
+
{ "path": "_nuxt/index.oton0Guf.js", "expected": true },
|
|
20
|
+
{ "path": "_astro/about.DYyuCeEr.css", "expected": true },
|
|
21
|
+
{ "path": "_next/static/index.html", "expected": false },
|
|
22
|
+
{ "path": "_next/static/sitemap.xml", "expected": false },
|
|
23
|
+
{ "path": "_app/immutable/manifest.txt", "expected": false },
|
|
24
|
+
{ "path": "_nextish/chunks/oton0Guf.js", "expected": false },
|
|
25
|
+
{ "path": "nested/_next/static/chunks/oton0Guf.js", "expected": false },
|
|
26
|
+
{ "path": "assets/index-BzeDGMM3.js", "expected": false },
|
|
27
|
+
{ "path": "assets/auth-client-P1Tx-Cyu.js", "expected": false },
|
|
28
|
+
{ "path": "assets/index-DYyuCeEr.js", "expected": false },
|
|
29
|
+
{ "path": "assets/index-9f8e7d6c.js", "expected": false },
|
|
30
|
+
{ "path": "assets/D3GeoMap.js", "expected": false },
|
|
31
|
+
{ "path": "assets/index.js", "expected": false },
|
|
32
|
+
{ "path": "assets/client-widget.js", "expected": false },
|
|
33
|
+
{ "path": "app.1a2b3c4d.css", "expected": false },
|
|
34
|
+
{ "path": "vendor.3f9a2b7e.js", "expected": false },
|
|
35
|
+
{ "path": "static/js/main.d41d8cd98f00b204e9800998.js", "expected": false },
|
|
36
|
+
{ "path": "index.html", "expected": false },
|
|
37
|
+
{ "path": "robots.txt", "expected": false },
|
|
38
|
+
{ "path": "config.xml", "expected": false },
|
|
39
|
+
{ "path": "page.php", "expected": false },
|
|
40
|
+
{ "path": "MyComponent.js", "expected": false },
|
|
41
|
+
{ "path": "image01.png", "expected": false }
|
|
42
|
+
],
|
|
43
|
+
"safeContentType": [
|
|
44
|
+
{
|
|
45
|
+
"path": "index.php",
|
|
46
|
+
"mime": "application/x-httpd-php",
|
|
47
|
+
"expected": "text/plain; charset=utf-8"
|
|
48
|
+
},
|
|
49
|
+
{ "path": "lib.phar", "mime": "application/zip", "expected": "application/octet-stream" },
|
|
50
|
+
{
|
|
51
|
+
"path": "assets/main.js",
|
|
52
|
+
"mime": "text/javascript; charset=utf-8",
|
|
53
|
+
"expected": "text/javascript; charset=utf-8"
|
|
54
|
+
},
|
|
55
|
+
{ "path": "logo.svg", "mime": "image/svg+xml", "expected": "image/svg+xml" }
|
|
56
|
+
]
|
|
57
|
+
}
|
|
@@ -7,13 +7,47 @@
|
|
|
7
7
|
// (static-runtime-policy.fixtures.json). Do not add platform/filesystem
|
|
8
8
|
// behavior here.
|
|
9
9
|
export const PHP_LIKE_EXTENSIONS = ["php", "php3", "php4", "php5", "php7", "php8", "phtml", "phar"];
|
|
10
|
+
// The internal-redirect/sendfile family: headers that do not describe a response, they
|
|
11
|
+
// instruct the web server to produce a different one. Under nginx+php-fpm
|
|
12
|
+
// X-Accel-Redirect (and every vendor spelling of it) turns a response into a server-side
|
|
13
|
+
// read of an arbitrary internal path — a private-path disclosure primitive — while
|
|
14
|
+
// X-Accel-Limit-Rate pins the serving worker for the length of the transfer.
|
|
15
|
+
//
|
|
16
|
+
// These are dangerous from ANY origin we do not control, so this family is factored out
|
|
17
|
+
// of the platform-managed list below: a relay lane (runtime/engine/runtime/proxy.php)
|
|
18
|
+
// must drop exactly this set from an untrusted upstream while still relaying the
|
|
19
|
+
// ordinary response headers (location, content-encoding, content-range, allow) that the
|
|
20
|
+
// rest of the managed list contains.
|
|
21
|
+
export const INTERNAL_REDIRECT_RESPONSE_HEADERS = [
|
|
22
|
+
"x-accel-buffering",
|
|
23
|
+
"x-accel-charset",
|
|
24
|
+
"x-accel-expires",
|
|
25
|
+
"x-accel-limit-rate",
|
|
26
|
+
"x-accel-redirect",
|
|
27
|
+
"x-lighttpd-send-file",
|
|
28
|
+
"x-lighttpd-sendfile",
|
|
29
|
+
"x-lighttpd-sendfile2",
|
|
30
|
+
"x-reproxy-url",
|
|
31
|
+
"x-sendfile",
|
|
32
|
+
];
|
|
10
33
|
// Rejected/platform-managed response headers (internal-docs/platform.md "Routing And
|
|
11
|
-
// Headers"): user `_headers` rules can never set or remove these. The
|
|
12
|
-
// internal-redirect/sendfile family
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
34
|
+
// Headers"): user `_headers` rules can never set or remove these. The
|
|
35
|
+
// internal-redirect/sendfile family above is spread in, so it stays a strict subset —
|
|
36
|
+
// anything the proxy lane refuses to relay is also refused from `_headers`. The rest is
|
|
37
|
+
// the connection and transport surface: hop-by-hop names (Connection, Keep-Alive, TE,
|
|
38
|
+
// Trailer, Transfer-Encoding, Upgrade, Proxy-*), framing, and the edge-cache trio.
|
|
39
|
+
//
|
|
40
|
+
// `isPlatformManagedResponseHeader` — not this list alone — is the policy: the reserved
|
|
41
|
+
// `x-spacefast-*` / `x-stattic-*` namespaces below carry the platform's own response
|
|
42
|
+
// signature (X-Spacefast-Runtime, X-Spacefast-Version, X-Spacefast-Reason, …), so user
|
|
43
|
+
// rules can never forge or clobber them.
|
|
44
|
+
//
|
|
45
|
+
// Every enforcement point derives from here: the `_headers` compiler in
|
|
46
|
+
// @spacefast/routing imports it directly, the PHP runtime maps and prefixes are
|
|
47
|
+
// generated from it into runtime/engine/shared/safety.php, and the Rust authorities
|
|
48
|
+
// (crates/stattic-runtime-core policy.rs, crates/stattic-zero-runner
|
|
49
|
+
// response_headers.rs) are drift-guarded against it by
|
|
50
|
+
// apps/control-plane/src/runtime/php-policy-parity.test.ts.
|
|
17
51
|
export const PLATFORM_MANAGED_RESPONSE_HEADERS = [
|
|
18
52
|
"accept-ranges",
|
|
19
53
|
"age",
|
|
@@ -28,21 +62,31 @@ export const PLATFORM_MANAGED_RESPONSE_HEADERS = [
|
|
|
28
62
|
"cookie",
|
|
29
63
|
"date",
|
|
30
64
|
"host",
|
|
65
|
+
"keep-alive",
|
|
31
66
|
"location",
|
|
32
67
|
"netlify-cdn-cache-control",
|
|
68
|
+
"proxy-authenticate",
|
|
69
|
+
"proxy-authorization",
|
|
33
70
|
"server",
|
|
34
71
|
"set-cookie",
|
|
35
72
|
"strict-transport-security",
|
|
36
73
|
"surrogate-control",
|
|
74
|
+
"te",
|
|
37
75
|
"trailer",
|
|
38
76
|
"transfer-encoding",
|
|
39
77
|
"upgrade",
|
|
40
78
|
"vary",
|
|
41
|
-
|
|
42
|
-
"x-accel-redirect",
|
|
43
|
-
"x-lighttpd-send-file",
|
|
44
|
-
"x-sendfile",
|
|
79
|
+
...INTERNAL_REDIRECT_RESPONSE_HEADERS,
|
|
45
80
|
];
|
|
81
|
+
/** Reserved response-header namespaces owned by the platform's own serving signature. */
|
|
82
|
+
export const PLATFORM_MANAGED_RESPONSE_HEADER_PREFIXES = ["x-spacefast-", "x-stattic-"];
|
|
83
|
+
const PLATFORM_MANAGED_RESPONSE_HEADER_SET = new Set(PLATFORM_MANAGED_RESPONSE_HEADERS);
|
|
84
|
+
/** True when user rules may neither set nor remove this response header. */
|
|
85
|
+
export function isPlatformManagedResponseHeader(name) {
|
|
86
|
+
const lower = name.trim().toLowerCase();
|
|
87
|
+
return (PLATFORM_MANAGED_RESPONSE_HEADER_SET.has(lower) ||
|
|
88
|
+
PLATFORM_MANAGED_RESPONSE_HEADER_PREFIXES.some((prefix) => lower.startsWith(prefix)));
|
|
89
|
+
}
|
|
46
90
|
export const NON_IMMUTABLE_EXTENSIONS = ["html", "htm", "php", "txt", "xml"];
|
|
47
91
|
const PHP_LIKE_EXTENSION_SET = new Set(PHP_LIKE_EXTENSIONS);
|
|
48
92
|
const NON_IMMUTABLE_EXTENSION_SET = new Set(NON_IMMUTABLE_EXTENSIONS);
|
|
@@ -24,6 +24,9 @@ export declare class UploadTargetError extends Error {
|
|
|
24
24
|
readonly status: number;
|
|
25
25
|
constructor(target: UploadTarget, status: number, message: string);
|
|
26
26
|
}
|
|
27
|
+
export declare function uploadPageHasRemainder(page: UploadSession): boolean;
|
|
28
|
+
export declare const UPLOAD_STALLED_RESUME_MAX_ATTEMPTS = 3;
|
|
29
|
+
export declare function uploadQueueAdvanced(before: UploadSession, after: UploadSession | null): boolean;
|
|
27
30
|
export declare function executeUploadSession(input: {
|
|
28
31
|
session: UploadSession;
|
|
29
32
|
targets?: readonly UploadTarget[] | undefined;
|
|
@@ -8,6 +8,37 @@ export class UploadTargetError extends Error {
|
|
|
8
8
|
this.name = "UploadTargetError";
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
+
// Manifest paging policy — ONE definition, shared by every uploader (the CLI
|
|
12
|
+
// and the control plane's inline uploader).
|
|
13
|
+
//
|
|
14
|
+
// `targets` is a single instruction page, bounded by the instruction payload
|
|
15
|
+
// budget; `summary.upload` counts the whole declared manifest. A short page
|
|
16
|
+
// therefore means a remainder that only `resume` hands out, and an uploader
|
|
17
|
+
// that stops at the first page finalizes a version the runtime rejects with
|
|
18
|
+
// `version_upload_incomplete`. A complete page means there is nothing left to
|
|
19
|
+
// ask for — don't re-resume to double-check the uploads, since the runtime
|
|
20
|
+
// verifies size and sha256 on every PUT and finalize independently enumerates
|
|
21
|
+
// anything still missing.
|
|
22
|
+
export function uploadPageHasRemainder(page) {
|
|
23
|
+
return page.summary.upload > page.targets.length;
|
|
24
|
+
}
|
|
25
|
+
// Resume mints the next page from runtime session truth, so a converging
|
|
26
|
+
// session always hands back different work. A page that repeats the previous
|
|
27
|
+
// one is a session that is not draining; retry it a bounded number of times,
|
|
28
|
+
// then fail loudly rather than page forever.
|
|
29
|
+
export const UPLOAD_STALLED_RESUME_MAX_ATTEMPTS = 3;
|
|
30
|
+
export function uploadQueueAdvanced(before, after) {
|
|
31
|
+
if (!after || after.targets.length === 0) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
if (after.targets.length < before.targets.length) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
if (after.targets.length > before.targets.length) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return after.targets.some((target, index) => target.path !== before.targets[index]?.path);
|
|
41
|
+
}
|
|
11
42
|
async function runConcurrent(items, concurrency, fn) {
|
|
12
43
|
let nextIndex = 0;
|
|
13
44
|
const runWorker = async () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spacefast/common",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Shared TypeScript contracts and utilities for Spacefast packages.",
|
|
6
6
|
"repository": {
|
|
@@ -91,8 +91,10 @@
|
|
|
91
91
|
}
|
|
92
92
|
},
|
|
93
93
|
"dependencies": {
|
|
94
|
-
"@tanstack/react-query": "^5.101.
|
|
95
|
-
"
|
|
96
|
-
"
|
|
94
|
+
"@tanstack/react-query": "^5.101.4",
|
|
95
|
+
"culori": "^4.0.2",
|
|
96
|
+
"js-yaml": "^4.1.1",
|
|
97
|
+
"smol-toml": "^1.7.0",
|
|
98
|
+
"zod": "^4.4.3"
|
|
97
99
|
}
|
|
98
100
|
}
|