@spacefast/common 0.0.24 → 0.2.1
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/brand-assets/LICENSE-Haskoy.txt +93 -0
- package/brand-assets/haskoy-latin-variable.woff2 +0 -0
- package/brand-assets/spacefast-favicon.svg +4 -4
- package/brand-assets/spacefast-sf-full-bleed.svg +3 -3
- package/brand-assets/spacefast-wordmark.svg +2 -4
- package/dist/agents/connect-targets.d.ts +6 -146
- package/dist/agents/connect-targets.js +63 -295
- package/dist/agents/private-key-oauth.d.ts +31 -2
- package/dist/agents/private-key-oauth.js +166 -92
- package/dist/agents/registry/core.d.ts +292 -0
- package/dist/agents/registry/core.js +1388 -0
- package/dist/agents/registry/deeplink-probes.d.ts +23 -0
- package/dist/agents/registry/deeplink-probes.js +18 -0
- package/dist/agents/registry/node.d.ts +56 -0
- package/dist/agents/registry/node.js +339 -0
- package/dist/brand-assets-build.js +3 -6
- package/dist/brand-assets.d.ts +5 -15
- package/dist/brand-assets.js +12 -14
- package/dist/brand.d.ts +17 -0
- package/dist/brand.js +24 -4
- package/dist/config/domains.d.ts +79 -12
- package/dist/config/domains.js +128 -29
- package/dist/config/index.js +1 -2
- package/dist/contracts/abuse.js +9 -24
- package/dist/contracts/access-profiles.d.ts +86 -0
- package/dist/contracts/access-profiles.js +89 -0
- package/dist/contracts/access.d.ts +24 -30
- package/dist/contracts/access.js +33 -64
- package/dist/contracts/activity.d.ts +18 -1
- package/dist/contracts/activity.js +72 -26
- package/dist/contracts/analytics.js +8 -10
- package/dist/contracts/api-keys.d.ts +77 -52
- package/dist/contracts/api-keys.js +44 -24
- package/dist/contracts/application-journal.d.ts +216 -0
- package/dist/contracts/application-journal.js +167 -0
- package/dist/contracts/auth.d.ts +90 -17
- package/dist/contracts/auth.js +86 -17
- package/dist/contracts/beta.d.ts +9 -4
- package/dist/contracts/beta.js +20 -16
- package/dist/contracts/billing.d.ts +2 -1
- package/dist/contracts/billing.js +37 -11
- package/dist/contracts/bootstrap.d.ts +791 -0
- package/dist/contracts/bootstrap.js +51 -0
- package/dist/contracts/builds.d.ts +209 -18
- package/dist/contracts/builds.js +93 -27
- package/dist/contracts/channels.d.ts +43 -0
- package/dist/contracts/channels.js +25 -9
- package/dist/contracts/cli.d.ts +7 -0
- package/dist/contracts/cli.js +6 -0
- package/dist/contracts/collab-public.d.ts +1 -1
- package/dist/contracts/collab-public.js +5 -8
- package/dist/contracts/comments.d.ts +44 -34
- package/dist/contracts/comments.js +107 -77
- package/dist/contracts/commerce.d.ts +165 -0
- package/dist/contracts/commerce.js +146 -0
- package/dist/contracts/common.d.ts +3 -3
- package/dist/contracts/common.js +20 -31
- package/dist/contracts/content-contract-verification.d.ts +521 -0
- package/dist/contracts/content-contract-verification.js +320 -0
- package/dist/contracts/content-platform-fixture.d.ts +1278 -0
- package/dist/contracts/content-platform-fixture.js +44 -0
- package/dist/contracts/content-program.d.ts +994 -0
- package/dist/contracts/content-program.js +658 -0
- package/dist/contracts/content-sync.d.ts +290 -0
- package/dist/contracts/content-sync.js +167 -0
- package/dist/contracts/content.d.ts +432 -0
- package/dist/contracts/content.js +303 -0
- package/dist/contracts/continuation.d.ts +17 -1
- package/dist/contracts/continuation.js +23 -23
- package/dist/contracts/countries.js +3 -4
- package/dist/contracts/crons.d.ts +52 -0
- package/dist/contracts/crons.js +60 -0
- package/dist/contracts/dashboard-prefs.d.ts +56 -0
- package/dist/contracts/dashboard-prefs.js +51 -0
- package/dist/contracts/device-auth.d.ts +234 -37
- package/dist/contracts/device-auth.js +267 -53
- package/dist/contracts/docs.d.ts +1 -5
- package/dist/contracts/docs.js +7 -15
- package/dist/contracts/domains.d.ts +501 -93
- package/dist/contracts/domains.js +193 -55
- package/dist/contracts/email-preferences.d.ts +3 -3
- package/dist/contracts/email-preferences.js +6 -7
- package/dist/contracts/enums.d.ts +27 -26
- package/dist/contracts/enums.js +68 -61
- package/dist/contracts/error-code-meta.d.ts +283 -7
- package/dist/contracts/error-code-meta.js +97 -5
- package/dist/contracts/error-codes.d.ts +5 -5
- package/dist/contracts/error-codes.js +82 -17
- package/dist/contracts/events.d.ts +100 -20
- package/dist/contracts/events.js +107 -20
- package/dist/contracts/execution.d.ts +48 -64
- package/dist/contracts/execution.js +52 -62
- package/dist/contracts/feature-lifecycle.d.ts +73 -27
- package/dist/contracts/feature-lifecycle.js +86 -26
- package/dist/contracts/features.d.ts +68 -19
- package/dist/contracts/features.js +42 -41
- package/dist/contracts/fixtures/content-platform-v1.json +1108 -0
- package/dist/contracts/frame-session.d.ts +192 -0
- package/dist/contracts/frame-session.js +164 -0
- package/dist/contracts/functions.d.ts +338 -164
- package/dist/contracts/functions.js +367 -198
- package/dist/contracts/git.d.ts +27 -33
- package/dist/contracts/git.js +10 -11
- package/dist/contracts/grant-copy.d.ts +43 -0
- package/dist/contracts/grant-copy.js +44 -0
- package/dist/contracts/grants.d.ts +62 -54
- package/dist/contracts/grants.js +124 -23
- package/dist/contracts/ids.d.ts +4 -1
- package/dist/contracts/ids.js +6 -3
- package/dist/contracts/internal.d.ts +8 -18
- package/dist/contracts/internal.js +13 -14
- package/dist/contracts/mcp.d.ts +28 -0
- package/dist/contracts/mcp.js +28 -0
- package/dist/contracts/me.d.ts +6 -1
- package/dist/contracts/me.js +12 -6
- package/dist/contracts/notifications.d.ts +27 -29
- package/dist/contracts/notifications.js +9 -4
- package/dist/contracts/oauth-resources.d.ts +112 -10
- package/dist/contracts/oauth-resources.js +116 -11
- package/dist/contracts/oauth-scope-actions.d.ts +90 -0
- package/dist/contracts/oauth-scope-actions.js +126 -0
- package/dist/contracts/operations.d.ts +27 -4
- package/dist/contracts/operations.js +12 -6
- package/dist/contracts/pages.d.ts +31 -7
- package/dist/contracts/pages.js +22 -5
- package/dist/contracts/partner-notifications.d.ts +3 -0
- package/dist/contracts/partner-notifications.js +65 -0
- package/dist/contracts/{platform.d.ts → partner.d.ts} +29 -42
- package/dist/contracts/{platform.js → partner.js} +27 -40
- package/dist/contracts/plan-policy.js +1 -1
- package/dist/contracts/principal-assertion.d.ts +43 -0
- package/dist/contracts/principal-assertion.js +67 -0
- package/dist/contracts/principals.d.ts +73 -0
- package/dist/contracts/principals.js +59 -0
- package/dist/contracts/privacy.d.ts +11 -0
- package/dist/contracts/privacy.js +17 -0
- package/dist/contracts/problem-document.js +3 -4
- package/dist/contracts/publish-archive.d.ts +269 -161
- package/dist/contracts/publish-archive.js +11 -1
- package/dist/contracts/push-new.d.ts +8 -8
- package/dist/contracts/quotas.js +5 -5
- package/dist/contracts/realtime.d.ts +52 -0
- package/dist/contracts/realtime.js +54 -0
- package/dist/contracts/repository-connections.d.ts +44 -31
- package/dist/contracts/repository-connections.js +17 -5
- package/dist/contracts/resources.d.ts +105 -14
- package/dist/contracts/resources.js +150 -26
- package/dist/contracts/route-inventory.d.ts +358 -0
- package/dist/contracts/route-inventory.js +141 -0
- package/dist/contracts/runtime-api.d.ts +206 -82
- package/dist/contracts/runtime-api.js +131 -70
- package/dist/contracts/runtime-app.d.ts +13 -23
- package/dist/contracts/runtime-app.js +39 -24
- package/dist/contracts/runtime-components.d.ts +143 -0
- package/dist/contracts/runtime-components.js +199 -0
- package/dist/contracts/runtime-db.d.ts +49 -23
- package/dist/contracts/runtime-db.js +87 -22
- package/dist/contracts/runtime-purge.d.ts +8 -0
- package/dist/contracts/runtime-purge.js +5 -0
- package/dist/contracts/runtime-services.d.ts +43 -75
- package/dist/contracts/runtime-services.js +29 -49
- package/dist/contracts/runtime-storage.d.ts +15 -14
- package/dist/contracts/runtime-storage.js +30 -14
- package/dist/contracts/sf-config-v1.d.ts +48 -14
- package/dist/contracts/slugs.js +13 -4
- package/dist/contracts/space-config.d.ts +283 -19
- package/dist/contracts/space-config.js +430 -80
- package/dist/contracts/spaces.d.ts +376 -290
- package/dist/contracts/spaces.js +200 -135
- package/dist/contracts/superadmin-activity.d.ts +3 -43
- package/dist/contracts/superadmin-activity.js +6 -30
- package/dist/contracts/superadmin-emails.d.ts +1 -0
- package/dist/contracts/superadmin-emails.js +17 -1
- package/dist/contracts/superadmin-runtime.d.ts +199 -0
- package/dist/contracts/superadmin-runtime.js +141 -0
- package/dist/contracts/superadmin-search.d.ts +22 -2
- package/dist/contracts/superadmin-search.js +14 -6
- package/dist/contracts/superadmin-spaces.d.ts +438 -189
- package/dist/contracts/superadmin-spaces.js +131 -25
- package/dist/contracts/superadmin-teams.d.ts +5 -2
- package/dist/contracts/superadmin-teams.js +1 -2
- package/dist/contracts/superadmin-tenants.d.ts +627 -12
- package/dist/contracts/superadmin-tenants.js +32 -13
- package/dist/contracts/superadmin.d.ts +232 -37
- package/dist/contracts/superadmin.js +106 -22
- package/dist/contracts/tags.d.ts +85 -58
- package/dist/contracts/tags.js +47 -37
- package/dist/contracts/teams.d.ts +86 -26
- package/dist/contracts/teams.js +90 -31
- package/dist/contracts/tenants.d.ts +135 -0
- package/dist/contracts/tenants.js +120 -0
- package/dist/contracts/test-triggers.d.ts +70 -0
- package/dist/contracts/test-triggers.js +116 -0
- package/dist/contracts/theme-json.js +3 -8
- package/dist/contracts/transfers.d.ts +1 -0
- package/dist/contracts/transfers.js +3 -2
- package/dist/contracts/usage.d.ts +209 -0
- package/dist/contracts/usage.js +124 -12
- package/dist/contracts/variables.d.ts +2 -2
- package/dist/contracts/variables.js +9 -13
- package/dist/contracts/webhooks.d.ts +13 -5
- package/dist/contracts/webhooks.js +3 -1
- package/dist/contracts/zero.d.ts +72 -81
- package/dist/contracts/zero.js +80 -78
- package/dist/dashboard-paths/index.d.ts +24 -21
- package/dist/dashboard-paths/index.js +35 -47
- package/dist/dashboard-paths/route-reservations.generated.d.ts +2 -0
- package/dist/dashboard-paths/route-reservations.generated.js +36 -0
- package/dist/docs/agent-arrival.d.ts +92 -0
- package/dist/docs/agent-arrival.js +227 -0
- package/dist/docs/agent-output-policy.d.ts +6 -0
- package/dist/docs/agent-output-policy.js +22 -0
- package/dist/docs/agent-prose.d.ts +12 -18
- package/dist/docs/agent-prose.js +73 -51
- package/dist/docs/agent-setup.d.ts +72 -41
- package/dist/docs/agent-setup.js +339 -436
- package/dist/docs/catalog.d.ts +153 -95
- package/dist/docs/catalog.js +163 -48
- package/dist/docs/error-docs.d.ts +2098 -1
- package/dist/docs/error-docs.js +421 -144
- package/dist/docs/index-build.d.ts +0 -1
- package/dist/docs/index-build.js +2 -3
- package/dist/docs/page-context-prompt.d.ts +77 -0
- package/dist/docs/page-context-prompt.js +131 -0
- package/dist/docs/reference-urls.d.ts +46 -0
- package/dist/docs/reference-urls.js +79 -0
- package/dist/docs/search.d.ts +6 -8
- package/dist/docs/search.js +10 -13
- package/dist/docs/skill-distribution.d.ts +4 -1
- package/dist/docs/skill-distribution.js +10 -5
- package/dist/docs/skills.d.ts +120 -120
- package/dist/docs/skills.js +121 -73
- package/dist/docs/start-prompts.d.ts +45 -0
- package/dist/docs/start-prompts.js +62 -0
- package/dist/domain-exploration.js +9 -13
- package/dist/og-template.d.ts +56 -0
- package/dist/og-template.js +56 -0
- package/dist/slug-policy/index.js +5 -11
- package/dist/test-helpers/fetch-stub.js +1 -0
- package/dist/utils/browser-credential.d.ts +13 -6
- package/dist/utils/browser-credential.js +14 -7
- package/dist/utils/build-settings.d.ts +21 -1
- package/dist/utils/build-settings.js +133 -15
- package/dist/utils/canonical-json.d.ts +3 -5
- package/dist/utils/canonical-json.js +4 -5
- package/dist/utils/cast-transport.d.ts +5 -17
- package/dist/utils/cast-transport.js +6 -19
- package/dist/utils/claim-token.js +1 -2
- package/dist/utils/comment-avatars.js +4 -6
- package/dist/utils/concurrency.js +3 -3
- package/dist/utils/content-type.d.ts +7 -6
- package/dist/utils/content-type.js +73 -51
- package/dist/utils/credential-policy.d.ts +50 -6
- package/dist/utils/credential-policy.js +126 -59
- package/dist/utils/dns-instructions.js +9 -9
- package/dist/utils/egress-policy.fixtures.json +1 -1
- package/dist/utils/error-code.js +1 -0
- package/dist/utils/generate-space-name.d.ts +3 -8
- package/dist/utils/generate-space-name.js +3 -8
- package/dist/utils/grant-decision.fixtures.json +2 -2
- package/dist/utils/grants.d.ts +0 -1
- package/dist/utils/grants.js +7 -8
- package/dist/utils/gravatar.d.ts +2 -4
- package/dist/utils/gravatar.js +6 -12
- package/dist/utils/id-hints.js +14 -23
- package/dist/utils/idempotency.d.ts +3 -3
- package/dist/utils/idempotency.js +6 -7
- package/dist/utils/local-space-state.d.ts +23 -26
- package/dist/utils/local-space-state.js +46 -46
- package/dist/utils/oauth-signed-query.d.ts +3 -5
- package/dist/utils/oauth-signed-query.js +6 -9
- package/dist/utils/one-shot-replay.d.ts +7 -6
- package/dist/utils/one-shot-replay.js +3 -5
- package/dist/utils/page-colors.d.ts +15 -19
- package/dist/utils/page-colors.js +23 -45
- package/dist/utils/page-fonts.d.ts +1 -1
- package/dist/utils/page-fonts.js +8 -20
- package/dist/utils/page-preview.d.ts +0 -1
- package/dist/utils/page-preview.js +0 -1
- package/dist/utils/pages.d.ts +33 -3
- package/dist/utils/pages.js +83 -30
- package/dist/utils/privacy-regions.d.ts +19 -0
- package/dist/utils/privacy-regions.js +91 -0
- package/dist/utils/publish-form-data.d.ts +4 -5
- package/dist/utils/publish-form-data.js +2 -3
- package/dist/utils/publish-policy.d.ts +11 -17
- package/dist/utils/publish-policy.fixtures.json +11 -5
- package/dist/utils/publish-policy.js +65 -110
- package/dist/utils/query-client.d.ts +2 -0
- package/dist/utils/query-client.js +10 -1
- package/dist/utils/runtime-paths.d.ts +4 -4
- package/dist/utils/runtime-paths.js +6 -8
- package/dist/utils/runtime-upload.d.ts +9 -0
- package/dist/utils/runtime-upload.js +12 -0
- package/dist/utils/secure-local-file.d.ts +3 -3
- package/dist/utils/secure-local-file.js +23 -40
- package/dist/utils/space-config.d.ts +12 -15
- package/dist/utils/space-config.js +13 -16
- package/dist/utils/static-runtime-policy.d.ts +10 -7
- package/dist/utils/static-runtime-policy.fixtures.json +38 -41
- package/dist/utils/static-runtime-policy.generated.d.ts +16 -0
- package/dist/utils/static-runtime-policy.generated.js +70 -0
- package/dist/utils/static-runtime-policy.js +31 -132
- package/dist/utils/storage-policy.js +1 -2
- package/dist/utils/upload-session.d.ts +4 -1
- package/dist/utils/upload-session.js +41 -19
- package/dist/utils/version-path.js +11 -19
- package/dist/utils/wpcom-auth-redirects.d.ts +5 -14
- package/dist/utils/wpcom-auth-redirects.js +1 -4
- package/dist/vocabulary.d.ts +13 -13
- package/dist/vocabulary.js +52 -27
- package/package.json +15 -18
- package/dist/agents/client-registry.d.ts +0 -22
- package/dist/agents/client-registry.js +0 -41
- package/dist/docs/agent-handoff-document.d.ts +0 -15
- package/dist/docs/agent-handoff-document.js +0 -180
- package/dist/docs/agent-solutions.d.ts +0 -110
- package/dist/docs/agent-solutions.js +0 -183
- package/dist/utils/query-keys.d.ts +0 -84
- package/dist/utils/query-keys.js +0 -108
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// `queued` means the purge journal durably owns the work; the edge provider
|
|
3
|
+
// call may not have run yet. `pending` is narrower: the synchronous worker kick
|
|
4
|
+
// never reached the purge entrypoint, so maintenance still owes the attempt.
|
|
5
|
+
export const runtimePurgeStatusSchema = z.enum(["queued", "ok", "failed", "pending"]);
|
|
@@ -2,30 +2,18 @@
|
|
|
2
2
|
* Platform services that tenant code reaches through the runtime rather than
|
|
3
3
|
* through a credential of its own: Gravatar, spam checking, and mail.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Every call is brokered, so no credential is ever in tenant reach. Zero hands
|
|
6
|
+
* these to a handler as `ctx.gravatar` / `ctx.spam` / `ctx.email`; Functions
|
|
7
|
+
* binds them as `env.GRAVATAR` / `env.SPAM` / `env.EMAIL`, with the same method
|
|
8
|
+
* names and fields. Zero's `check` narrows the input because its HTTP host can
|
|
9
|
+
* add request metadata; a detached Functions call supplies it explicitly.
|
|
7
10
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* capsule is worse. Every call below is brokered: the runtime attaches
|
|
11
|
-
* authority outside the code that asked for the call.
|
|
12
|
-
* - **The interface is the contract, not the accessor.** Zero hands these to a
|
|
13
|
-
* handler as `ctx.gravatar` / `ctx.spam` / `ctx.email`; Functions binds them
|
|
14
|
-
* as `env.GRAVATAR` / `env.SPAM` / `env.EMAIL`. Method names and semantic
|
|
15
|
-
* fields stay shared. Zero's `check` narrows the input because its HTTP host
|
|
16
|
-
* can add request metadata; a detached Functions call supplies that metadata
|
|
17
|
-
* explicitly.
|
|
18
|
-
* - **The client is the same source on both tiers.** See
|
|
19
|
-
* `RUNTIME_SERVICE_CLIENT_SOURCE`: normalization, validation and the pure
|
|
20
|
-
* avatar-URL construction are one implementation injected into both runtimes,
|
|
21
|
-
* so the two tiers cannot drift into behaving differently.
|
|
22
|
-
*
|
|
23
|
-
* What differs between tiers is the transport under `call()`, and only that.
|
|
11
|
+
* `RUNTIME_SERVICE_CLIENT_SOURCE` is one implementation injected into both
|
|
12
|
+
* runtimes, so only the transport under `call()` differs between tiers.
|
|
24
13
|
*/
|
|
25
14
|
/**
|
|
26
|
-
* What Gravatar serves when an address has no image. `404`
|
|
27
|
-
*
|
|
28
|
-
* have to recognise as a placeholder.
|
|
15
|
+
* What Gravatar serves when an address has no image. `404` lets a caller detect
|
|
16
|
+
* absence by status instead of by recognising a generated placeholder.
|
|
29
17
|
*/
|
|
30
18
|
export declare const GRAVATAR_DEFAULTS: readonly ["404", "mp", "identicon", "monsterid", "wavatar", "retro", "robohash", "blank"];
|
|
31
19
|
export type GravatarDefault = (typeof GRAVATAR_DEFAULTS)[number];
|
|
@@ -34,7 +22,7 @@ export type GravatarRating = (typeof GRAVATAR_RATINGS)[number];
|
|
|
34
22
|
/** Gravatar's own ceiling. Larger values are refused rather than clamped. */
|
|
35
23
|
export declare const GRAVATAR_AVATAR_MAX_SIZE = 2048;
|
|
36
24
|
export type GravatarAvatarOptions = {
|
|
37
|
-
/** Requested square edge in pixels, 1
|
|
25
|
+
/** Requested square edge in pixels, 1 to 2048. */
|
|
38
26
|
size?: number;
|
|
39
27
|
/** Image to serve when the address has no Gravatar. */
|
|
40
28
|
default?: GravatarDefault;
|
|
@@ -49,9 +37,9 @@ export type GravatarVerifiedAccount = {
|
|
|
49
37
|
label: string | null;
|
|
50
38
|
};
|
|
51
39
|
/**
|
|
52
|
-
* The subset of the Gravatar profile
|
|
53
|
-
*
|
|
54
|
-
*
|
|
40
|
+
* The stable, public subset of the Gravatar profile. Not the raw upstream
|
|
41
|
+
* document: passing that through would make every upstream field addition a
|
|
42
|
+
* silent contract change.
|
|
55
43
|
*/
|
|
56
44
|
export type GravatarProfile = {
|
|
57
45
|
hash: string;
|
|
@@ -64,32 +52,24 @@ export type GravatarProfile = {
|
|
|
64
52
|
verifiedAccounts: GravatarVerifiedAccount[];
|
|
65
53
|
};
|
|
66
54
|
export type Gravatar = {
|
|
67
|
-
/**
|
|
68
|
-
* Pure and synchronous: an avatar URL is a hash and a query string, so it
|
|
69
|
-
* costs no network call and cannot fail. It stays on this interface anyway
|
|
70
|
-
* because an author looking for an avatar looks here, not in a utility
|
|
71
|
-
* module.
|
|
72
|
-
*/
|
|
55
|
+
/** Pure and synchronous: an avatar URL is a hash and a query string. */
|
|
73
56
|
avatarUrl(email: string, options?: GravatarAvatarOptions): string;
|
|
74
57
|
/** The profile behind an address, or null when the address has none. */
|
|
75
58
|
profile(email: string): Promise<GravatarProfile | null>;
|
|
76
59
|
};
|
|
77
60
|
/**
|
|
78
|
-
* Akismet's recognised content types. The
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* it, and inventing synonyms would only lose signal.
|
|
61
|
+
* Akismet's recognised content types. The vocabulary is Akismet's because the
|
|
62
|
+
* classifier is trained on it; the vendor name stays out of the API surface,
|
|
63
|
+
* because `ctx.spam` outlives whichever service answers it.
|
|
82
64
|
*/
|
|
83
65
|
export declare const SPAM_CONTENT_TYPES: readonly ["comment", "reply", "forum-post", "contact-form", "signup", "message"];
|
|
84
66
|
export type SpamContentType = (typeof SPAM_CONTENT_TYPES)[number];
|
|
85
67
|
/**
|
|
86
68
|
* One complete submission, as the classifier sees it. Detached runtimes such
|
|
87
|
-
* as Functions use this shape; Zero uses {@link RequestSpamSubmission}
|
|
88
|
-
*
|
|
69
|
+
* as Functions use this shape; Zero uses {@link RequestSpamSubmission} and
|
|
70
|
+
* fills the network fields itself.
|
|
89
71
|
*
|
|
90
|
-
* `userIp`
|
|
91
|
-
* accuracy drops sharply without them — hence `userIp` being required rather
|
|
92
|
-
* than another optional field an author would skip.
|
|
72
|
+
* `userIp` is required because accuracy drops sharply without it.
|
|
93
73
|
*/
|
|
94
74
|
export type SpamSubmission = {
|
|
95
75
|
/** The text being classified. */
|
|
@@ -106,9 +86,7 @@ export type SpamSubmission = {
|
|
|
106
86
|
authorUrl?: string;
|
|
107
87
|
/**
|
|
108
88
|
* Set to `"administrator"` for a trusted, authenticated operator of the
|
|
109
|
-
* space. Akismet passes that role unconditionally, so
|
|
110
|
-
* own escape hatch for their own team — it grants nothing beyond skipping a
|
|
111
|
-
* check the author asked for.
|
|
89
|
+
* space. Akismet passes that role unconditionally, so the check is skipped.
|
|
112
90
|
*/
|
|
113
91
|
authorRole?: "administrator";
|
|
114
92
|
/** ISO-8601 UTC. Defaults to the moment of the call. */
|
|
@@ -119,19 +97,17 @@ export type SpamSubmission = {
|
|
|
119
97
|
/**
|
|
120
98
|
* A spam check made while handling a visitor request.
|
|
121
99
|
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* through mutation arguments or an endpoint body.
|
|
100
|
+
* The runtime, not capsule code, supplies the visitor IP, user agent, referrer,
|
|
101
|
+
* and current URL from the trusted invocation envelope, so a browser cannot
|
|
102
|
+
* claim its own IP through mutation arguments or an endpoint body.
|
|
126
103
|
*/
|
|
127
104
|
export type RequestSpamSubmission = Omit<SpamSubmission, "userIp" | "userAgent" | "referrer" | "permalink">;
|
|
128
105
|
export type SpamVerdict = {
|
|
129
106
|
/** Whether the submission classifies as spam. */
|
|
130
107
|
spam: boolean;
|
|
131
108
|
/**
|
|
132
|
-
* Blatant, pervasive spam. Akismet's
|
|
133
|
-
*
|
|
134
|
-
* being folded into `spam`.
|
|
109
|
+
* Blatant, pervasive spam. Akismet's guidance is to drop it outright rather
|
|
110
|
+
* than hold it for review.
|
|
135
111
|
*/
|
|
136
112
|
discard: boolean;
|
|
137
113
|
};
|
|
@@ -157,10 +133,8 @@ export type RuntimeSpamRequestContext = {
|
|
|
157
133
|
permalink?: string;
|
|
158
134
|
};
|
|
159
135
|
/**
|
|
160
|
-
* The structured subset of Cloudflare's `SendEmail` binding, field for field
|
|
161
|
-
*
|
|
162
|
-
* Matching it is a portability decision, not an aesthetic one: a worker
|
|
163
|
-
* deployed straight to Cloudflare gets the native binding and the same
|
|
136
|
+
* The structured subset of Cloudflare's `SendEmail` binding, field for field: a
|
|
137
|
+
* worker deployed straight to Cloudflare gets the native binding, and the same
|
|
164
138
|
* message-building code has to typecheck against both.
|
|
165
139
|
*/
|
|
166
140
|
export type EmailAddress = {
|
|
@@ -180,40 +154,34 @@ export type EmailMessage = {
|
|
|
180
154
|
};
|
|
181
155
|
export type SendEmail = {
|
|
182
156
|
/**
|
|
183
|
-
* Accepts one email effect. The identifier names the message
|
|
184
|
-
*
|
|
185
|
-
* observable from here — see the runtime's message views for that.
|
|
157
|
+
* Accepts one email effect. The identifier names the message, not a delivery;
|
|
158
|
+
* nothing beyond "queued" is observable here.
|
|
186
159
|
*/
|
|
187
160
|
send(message: EmailMessage): Promise<{
|
|
188
161
|
messageId: string;
|
|
189
162
|
}>;
|
|
190
163
|
};
|
|
191
164
|
/**
|
|
192
|
-
* The hosts a broker may reach on a tenant's behalf are
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
* declaration is enforced at both places a connection is actually made. A copy
|
|
196
|
-
* in this file would be a third statement of the same fact that nothing checks.
|
|
165
|
+
* The hosts a broker may reach on a tenant's behalf are NOT listed here. That
|
|
166
|
+
* table lives in `stattic-runtime-core`'s egress policy, generated into both
|
|
167
|
+
* the runtime's PHP constants and the Rust broker.
|
|
197
168
|
*
|
|
198
|
-
* The `gravatar.com` in the avatar URL below is
|
|
199
|
-
*
|
|
169
|
+
* The `gravatar.com` in the avatar URL below is a public URL handed to a
|
|
170
|
+
* browser, not an egress target.
|
|
200
171
|
*/
|
|
201
172
|
/**
|
|
202
173
|
* The client both runtimes inject, as source.
|
|
203
174
|
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
* "the same API" a fact about the code rather than a promise in a doc.
|
|
175
|
+
* A string rather than a module because neither runtime can import from npm
|
|
176
|
+
* here: Zero compiles a capsule to QuickJS bytecode with a generated prelude,
|
|
177
|
+
* and the Functions host injects modules into a tenant isolate it does not
|
|
178
|
+
* build.
|
|
209
179
|
*
|
|
210
180
|
* It closes over nothing of ours. The host defines `call(service, operation,
|
|
211
|
-
* payload)
|
|
212
|
-
* shapes returned to tenant code — is here, identical on both tiers.
|
|
181
|
+
* payload)`; everything else is here, identical on both tiers.
|
|
213
182
|
*
|
|
214
|
-
* The SHA-256 is hand-rolled
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
* implementation is the only way the signature can be identical.
|
|
183
|
+
* The SHA-256 is hand-rolled because QuickJS has no WebCrypto and
|
|
184
|
+
* `crypto.subtle` is async, which would make `avatarUrl` return a promise on
|
|
185
|
+
* one tier and a string on the other.
|
|
218
186
|
*/
|
|
219
187
|
export declare const RUNTIME_SERVICE_CLIENT_SOURCE: string;
|
|
@@ -2,33 +2,21 @@
|
|
|
2
2
|
* Platform services that tenant code reaches through the runtime rather than
|
|
3
3
|
* through a credential of its own: Gravatar, spam checking, and mail.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Every call is brokered, so no credential is ever in tenant reach. Zero hands
|
|
6
|
+
* these to a handler as `ctx.gravatar` / `ctx.spam` / `ctx.email`; Functions
|
|
7
|
+
* binds them as `env.GRAVATAR` / `env.SPAM` / `env.EMAIL`, with the same method
|
|
8
|
+
* names and fields. Zero's `check` narrows the input because its HTTP host can
|
|
9
|
+
* add request metadata; a detached Functions call supplies it explicitly.
|
|
7
10
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* capsule is worse. Every call below is brokered: the runtime attaches
|
|
11
|
-
* authority outside the code that asked for the call.
|
|
12
|
-
* - **The interface is the contract, not the accessor.** Zero hands these to a
|
|
13
|
-
* handler as `ctx.gravatar` / `ctx.spam` / `ctx.email`; Functions binds them
|
|
14
|
-
* as `env.GRAVATAR` / `env.SPAM` / `env.EMAIL`. Method names and semantic
|
|
15
|
-
* fields stay shared. Zero's `check` narrows the input because its HTTP host
|
|
16
|
-
* can add request metadata; a detached Functions call supplies that metadata
|
|
17
|
-
* explicitly.
|
|
18
|
-
* - **The client is the same source on both tiers.** See
|
|
19
|
-
* `RUNTIME_SERVICE_CLIENT_SOURCE`: normalization, validation and the pure
|
|
20
|
-
* avatar-URL construction are one implementation injected into both runtimes,
|
|
21
|
-
* so the two tiers cannot drift into behaving differently.
|
|
22
|
-
*
|
|
23
|
-
* What differs between tiers is the transport under `call()`, and only that.
|
|
11
|
+
* `RUNTIME_SERVICE_CLIENT_SOURCE` is one implementation injected into both
|
|
12
|
+
* runtimes, so only the transport under `call()` differs between tiers.
|
|
24
13
|
*/
|
|
25
14
|
/* -------------------------------------------------------------------------- */
|
|
26
15
|
/* Gravatar */
|
|
27
16
|
/* -------------------------------------------------------------------------- */
|
|
28
17
|
/**
|
|
29
|
-
* What Gravatar serves when an address has no image. `404`
|
|
30
|
-
*
|
|
31
|
-
* have to recognise as a placeholder.
|
|
18
|
+
* What Gravatar serves when an address has no image. `404` lets a caller detect
|
|
19
|
+
* absence by status instead of by recognising a generated placeholder.
|
|
32
20
|
*/
|
|
33
21
|
export const GRAVATAR_DEFAULTS = [
|
|
34
22
|
"404",
|
|
@@ -47,10 +35,9 @@ export const GRAVATAR_AVATAR_MAX_SIZE = 2048;
|
|
|
47
35
|
/* Spam */
|
|
48
36
|
/* -------------------------------------------------------------------------- */
|
|
49
37
|
/**
|
|
50
|
-
* Akismet's recognised content types. The
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* it, and inventing synonyms would only lose signal.
|
|
38
|
+
* Akismet's recognised content types. The vocabulary is Akismet's because the
|
|
39
|
+
* classifier is trained on it; the vendor name stays out of the API surface,
|
|
40
|
+
* because `ctx.spam` outlives whichever service answers it.
|
|
54
41
|
*/
|
|
55
42
|
export const SPAM_CONTENT_TYPES = [
|
|
56
43
|
"comment",
|
|
@@ -64,14 +51,12 @@ export const SPAM_CONTENT_TYPES = [
|
|
|
64
51
|
/* Upstreams */
|
|
65
52
|
/* -------------------------------------------------------------------------- */
|
|
66
53
|
/**
|
|
67
|
-
* The hosts a broker may reach on a tenant's behalf are
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* declaration is enforced at both places a connection is actually made. A copy
|
|
71
|
-
* in this file would be a third statement of the same fact that nothing checks.
|
|
54
|
+
* The hosts a broker may reach on a tenant's behalf are NOT listed here. That
|
|
55
|
+
* table lives in `stattic-runtime-core`'s egress policy, generated into both
|
|
56
|
+
* the runtime's PHP constants and the Rust broker.
|
|
72
57
|
*
|
|
73
|
-
* The `gravatar.com` in the avatar URL below is
|
|
74
|
-
*
|
|
58
|
+
* The `gravatar.com` in the avatar URL below is a public URL handed to a
|
|
59
|
+
* browser, not an egress target.
|
|
75
60
|
*/
|
|
76
61
|
/* -------------------------------------------------------------------------- */
|
|
77
62
|
/* The shared client */
|
|
@@ -79,20 +64,17 @@ export const SPAM_CONTENT_TYPES = [
|
|
|
79
64
|
/**
|
|
80
65
|
* The client both runtimes inject, as source.
|
|
81
66
|
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* "the same API" a fact about the code rather than a promise in a doc.
|
|
67
|
+
* A string rather than a module because neither runtime can import from npm
|
|
68
|
+
* here: Zero compiles a capsule to QuickJS bytecode with a generated prelude,
|
|
69
|
+
* and the Functions host injects modules into a tenant isolate it does not
|
|
70
|
+
* build.
|
|
87
71
|
*
|
|
88
72
|
* It closes over nothing of ours. The host defines `call(service, operation,
|
|
89
|
-
* payload)
|
|
90
|
-
* shapes returned to tenant code — is here, identical on both tiers.
|
|
73
|
+
* payload)`; everything else is here, identical on both tiers.
|
|
91
74
|
*
|
|
92
|
-
* The SHA-256 is hand-rolled
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* implementation is the only way the signature can be identical.
|
|
75
|
+
* The SHA-256 is hand-rolled because QuickJS has no WebCrypto and
|
|
76
|
+
* `crypto.subtle` is async, which would make `avatarUrl` return a promise on
|
|
77
|
+
* one tier and a string on the other.
|
|
96
78
|
*/
|
|
97
79
|
export const RUNTIME_SERVICE_CLIENT_SOURCE = String.raw `
|
|
98
80
|
const SERVICE_DEFAULTS = ${JSON.stringify(GRAVATAR_DEFAULTS)};
|
|
@@ -217,9 +199,8 @@ function sha256Hex(value) {
|
|
|
217
199
|
return hex;
|
|
218
200
|
}
|
|
219
201
|
|
|
220
|
-
// Gravatar's
|
|
221
|
-
//
|
|
222
|
-
// two accounts as far as Gravatar is concerned.
|
|
202
|
+
// Gravatar's identifier rule: trim and lower-case only. Dots and plus-tags are
|
|
203
|
+
// not stripped; two addresses that differ there are two Gravatar accounts.
|
|
223
204
|
function gravatarHash(email) {
|
|
224
205
|
if (typeof email !== "string" || email.trim() === "") {
|
|
225
206
|
throw invalid("An email address is required.");
|
|
@@ -402,9 +383,8 @@ function emailPayload(message) {
|
|
|
402
383
|
for (const name of Object.keys(message.headers)) {
|
|
403
384
|
const value = message.headers[name];
|
|
404
385
|
if (typeof value !== "string") throw invalid("Header " + name + " must be a string.");
|
|
405
|
-
// Refused here
|
|
406
|
-
//
|
|
407
|
-
// the boundary.
|
|
386
|
+
// Refused here so the author sees the field name they wrote. The broker
|
|
387
|
+
// refuses again; this is convenience, not the boundary.
|
|
408
388
|
if (/[^\x21-\x39\x3b-\x7e]/.test(name)) {
|
|
409
389
|
throw invalid("Header " + name + " is not a valid header name.");
|
|
410
390
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
/** Objects are addressed by a bare 128-bit random id
|
|
2
|
+
/** Objects are addressed by a bare 128-bit random id. There is no key and no visibility. */
|
|
3
3
|
export declare const runtimeStorageObjectIdSchema: z.ZodString;
|
|
4
4
|
/** The runtime-scoped, revocable read key that makes a `/__stattic/u/<id>` URL readable. */
|
|
5
5
|
export declare const runtimeStorageReadKeySchema: z.ZodString;
|
|
@@ -43,19 +43,19 @@ export declare const runtimeStorageListResponseSchema: z.ZodObject<{
|
|
|
43
43
|
}, z.core.$strict>;
|
|
44
44
|
export type RuntimeStorageListResponse = z.infer<typeof runtimeStorageListResponseSchema>;
|
|
45
45
|
export declare const runtimeStorageListPublicResponseSchema: z.ZodObject<{
|
|
46
|
-
data: z.ZodObject<{
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
46
|
+
data: z.ZodArray<z.ZodObject<{
|
|
47
|
+
id: z.ZodString;
|
|
48
|
+
contentType: z.ZodString;
|
|
49
|
+
createdAt: z.ZodString;
|
|
50
|
+
size: z.ZodNumber;
|
|
51
|
+
uploaderId: z.ZodString;
|
|
52
|
+
sha256: z.ZodString;
|
|
53
|
+
url: z.ZodString;
|
|
54
|
+
}, z.core.$strict>>;
|
|
55
|
+
pagination: z.ZodObject<{
|
|
56
|
+
nextCursor: z.ZodNullable<z.ZodString>;
|
|
57
57
|
hasMore: z.ZodBoolean;
|
|
58
|
-
}, z.core.$
|
|
58
|
+
}, z.core.$strip>;
|
|
59
59
|
}, z.core.$strip>;
|
|
60
60
|
export declare const runtimeStorageDeleteResponseSchema: z.ZodObject<{
|
|
61
61
|
id: z.ZodString;
|
|
@@ -97,7 +97,7 @@ export declare const runtimeStorageDeletePublicResponseSchema: z.ZodObject<{
|
|
|
97
97
|
path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
98
98
|
provider: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
99
99
|
registrar: "registrar";
|
|
100
|
-
|
|
100
|
+
infra: "infra";
|
|
101
101
|
dns: "dns";
|
|
102
102
|
runtime: "runtime";
|
|
103
103
|
}>>>;
|
|
@@ -119,6 +119,7 @@ export declare const runtimeStorageReadKeyRotateResponseSchema: z.ZodObject<{
|
|
|
119
119
|
purge: z.ZodObject<{
|
|
120
120
|
status: z.ZodEnum<{
|
|
121
121
|
failed: "failed";
|
|
122
|
+
queued: "queued";
|
|
122
123
|
pending: "pending";
|
|
123
124
|
ok: "ok";
|
|
124
125
|
}>;
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { CursorPaginationSchema, mutationEnvelope } from "./common.js";
|
|
3
|
+
import { runtimePurgeStatusSchema } from "./runtime-purge.js";
|
|
4
|
+
/** Objects are addressed by a bare 128-bit random id. There is no key and no visibility. */
|
|
4
5
|
export const runtimeStorageObjectIdSchema = z.string().regex(/^[a-f0-9]{32}$/);
|
|
5
6
|
/** The runtime-scoped, revocable read key that makes a `/__stattic/u/<id>` URL readable. */
|
|
6
7
|
export const runtimeStorageReadKeySchema = z.string().regex(/^[a-f0-9]{32}$/);
|
|
7
8
|
export const runtimeStorageListQuerySchema = z
|
|
8
9
|
.object({
|
|
9
|
-
cursor: z
|
|
10
|
-
|
|
10
|
+
cursor: z
|
|
11
|
+
.string()
|
|
12
|
+
.min(1)
|
|
13
|
+
.max(2_048)
|
|
14
|
+
.optional()
|
|
15
|
+
.describe("Opaque cursor from the previous page's `pagination.nextCursor`."),
|
|
16
|
+
limit: z.coerce
|
|
17
|
+
.number()
|
|
18
|
+
.int()
|
|
19
|
+
.min(1)
|
|
20
|
+
.max(100)
|
|
21
|
+
.default(50)
|
|
22
|
+
.describe("Maximum objects to return."),
|
|
11
23
|
})
|
|
12
24
|
.strict();
|
|
13
25
|
export const runtimeStorageObjectSchema = z
|
|
@@ -18,12 +30,15 @@ export const runtimeStorageObjectSchema = z
|
|
|
18
30
|
size: z.number().int().nonnegative(),
|
|
19
31
|
uploaderId: z.string().min(1).max(255),
|
|
20
32
|
sha256: z.string().regex(/^[a-f0-9]{64}$/),
|
|
21
|
-
// Path-relative
|
|
22
|
-
//
|
|
23
|
-
//
|
|
33
|
+
// Path-relative, carrying the read key current at response time:
|
|
34
|
+
// `/__stattic/u/<id>?k=<key>`. The caller absolutizes it against whichever
|
|
35
|
+
// of the space's hostnames it is presenting.
|
|
24
36
|
url: z.string().min(1),
|
|
25
37
|
})
|
|
26
38
|
.strict();
|
|
39
|
+
// The runtime's own wire shape for a storage page, which the control plane
|
|
40
|
+
// reads and then re-envelopes. `cursor`/`hasMore` here are the runtime's
|
|
41
|
+
// spelling; the public route below answers the one platform list envelope.
|
|
27
42
|
export const runtimeStorageListResponseSchema = z
|
|
28
43
|
.object({
|
|
29
44
|
objects: z.array(runtimeStorageObjectSchema),
|
|
@@ -31,7 +46,10 @@ export const runtimeStorageListResponseSchema = z
|
|
|
31
46
|
hasMore: z.boolean(),
|
|
32
47
|
})
|
|
33
48
|
.strict();
|
|
34
|
-
export const runtimeStorageListPublicResponseSchema =
|
|
49
|
+
export const runtimeStorageListPublicResponseSchema = z.object({
|
|
50
|
+
data: z.array(runtimeStorageObjectSchema),
|
|
51
|
+
pagination: CursorPaginationSchema,
|
|
52
|
+
});
|
|
35
53
|
export const runtimeStorageDeleteResponseSchema = z
|
|
36
54
|
.object({
|
|
37
55
|
id: runtimeStorageObjectIdSchema,
|
|
@@ -42,18 +60,16 @@ export const runtimeStorageDeletePublicResponseSchema = mutationEnvelope(runtime
|
|
|
42
60
|
export const runtimeStorageReadKeyResponseSchema = z
|
|
43
61
|
.object({ key: runtimeStorageReadKeySchema })
|
|
44
62
|
.strict();
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
// how that purge landed.
|
|
63
|
+
// Every URL minted under the old key answers 404 after rotation, so the runtime
|
|
64
|
+
// purges every hostname on the box and reports how that purge landed.
|
|
48
65
|
export const runtimeStorageReadKeyRotateResponseSchema = z
|
|
49
66
|
.object({
|
|
50
67
|
key: runtimeStorageReadKeySchema,
|
|
51
68
|
rotatedAt: z.string().datetime({ offset: true }),
|
|
52
|
-
// `none
|
|
53
|
-
// was nothing to purge.
|
|
69
|
+
// `none`: the runtime serves no hostname yet, so there was nothing to purge.
|
|
54
70
|
purge: z
|
|
55
71
|
.object({
|
|
56
|
-
status:
|
|
72
|
+
status: runtimePurgeStatusSchema,
|
|
57
73
|
mode: z.enum(["urls", "domain", "none"]),
|
|
58
74
|
urls: z.number().int().nonnegative().optional(),
|
|
59
75
|
})
|
|
@@ -4,10 +4,29 @@ export declare const SF_CONFIG_V1_FILES: readonly ["sf.jsonc", "spacefast.jsonc"
|
|
|
4
4
|
/** Published JSON Schema URL for the strict `sf.jsonc` v1 contract. */
|
|
5
5
|
export declare const SF_CONFIG_V1_SCHEMA_URL: `${string}/schemas/sf.v1.json`;
|
|
6
6
|
/**
|
|
7
|
-
* How a redirect answers. Omitting it means 302. There is no 200
|
|
8
|
-
* serves other content under the requested URL is a `rewrites`
|
|
7
|
+
* How a redirect answers. Omitting it means 302. There is no 200 and no 404:
|
|
8
|
+
* a rule that serves other content under the requested URL is a `rewrites`
|
|
9
|
+
* entry, with `notFound: true` when it should answer 404.
|
|
9
10
|
*/
|
|
10
11
|
export type SfConfigV1RedirectStatus = 301 | 302 | 303 | 307 | 308;
|
|
12
|
+
/**
|
|
13
|
+
* Query parameters a redirect or rewrite requires, as parameter name to
|
|
14
|
+
* capture name. `{ id: "id" }` is the `id=:id` token of a `_redirects` line.
|
|
15
|
+
*/
|
|
16
|
+
export type SfConfigV1QueryMatch = Record<string, string>;
|
|
17
|
+
/**
|
|
18
|
+
* One header operation: `{ key, value }` sets, `{ key, remove: true }` is the
|
|
19
|
+
* `!Name` line of a `_headers` block. A remove entry carries no value.
|
|
20
|
+
*/
|
|
21
|
+
export type SfConfigV1HeaderEntry = {
|
|
22
|
+
key: string;
|
|
23
|
+
value: string;
|
|
24
|
+
remove?: never;
|
|
25
|
+
} | {
|
|
26
|
+
key: string;
|
|
27
|
+
remove: true;
|
|
28
|
+
value?: never;
|
|
29
|
+
};
|
|
11
30
|
export type SfConfigV1 = {
|
|
12
31
|
$schema?: typeof SF_CONFIG_V1_SCHEMA_URL;
|
|
13
32
|
version: 1;
|
|
@@ -32,29 +51,35 @@ export type SfConfigV1 = {
|
|
|
32
51
|
source: string;
|
|
33
52
|
destination: string;
|
|
34
53
|
status?: SfConfigV1RedirectStatus;
|
|
54
|
+
/** Answer even when the request path resolves to a committed file, the `!` of a `_redirects` rule. */
|
|
55
|
+
force?: boolean;
|
|
56
|
+
query?: SfConfigV1QueryMatch;
|
|
35
57
|
}[];
|
|
36
58
|
/**
|
|
37
59
|
* Rewrite and proxy rules: the URL stays, the content comes from the
|
|
38
|
-
* destination. A path destination rewrites, an absolute URL proxies
|
|
39
|
-
*
|
|
40
|
-
*
|
|
60
|
+
* destination. A path destination rewrites, an absolute URL proxies. Both are
|
|
61
|
+
* the `/from /to 200` rule of `_redirects`, so they carry no status of their
|
|
62
|
+
* own. `notFound: true` answers 404 instead, and then the destination must be
|
|
63
|
+
* a path.
|
|
41
64
|
*/
|
|
42
65
|
rewrites?: {
|
|
43
66
|
source: string;
|
|
44
67
|
destination: string;
|
|
45
68
|
/** Let shared caches store the proxy response. Absolute-URL destinations only. */
|
|
46
69
|
cache?: "shared";
|
|
70
|
+
/** Rewrite even when the request path resolves to a committed file, the `!` of a `200!` / `404!` file rule. */
|
|
71
|
+
force?: boolean;
|
|
72
|
+
query?: SfConfigV1QueryMatch;
|
|
73
|
+
notFound?: boolean;
|
|
47
74
|
}[];
|
|
48
75
|
/**
|
|
49
|
-
* Response headers to set on matching requests. Headers are a
|
|
50
|
-
* map, so repeated names (Set-Cookie) survive
|
|
76
|
+
* Response headers to set or remove on matching requests. Headers are a
|
|
77
|
+
* list, not a map, so repeated names (Set-Cookie) survive and operations
|
|
78
|
+
* keep their order.
|
|
51
79
|
*/
|
|
52
80
|
headers?: {
|
|
53
81
|
source: string;
|
|
54
|
-
headers:
|
|
55
|
-
key: string;
|
|
56
|
-
value: string;
|
|
57
|
-
}[];
|
|
82
|
+
headers: SfConfigV1HeaderEntry[];
|
|
58
83
|
}[];
|
|
59
84
|
metadata?: {
|
|
60
85
|
title?: string;
|
|
@@ -67,6 +92,15 @@ export type SfConfigV1 = {
|
|
|
67
92
|
access?: {
|
|
68
93
|
public: string[];
|
|
69
94
|
};
|
|
95
|
+
/**
|
|
96
|
+
* Scheduled requests against this space's own paths. The compiled
|
|
97
|
+
* `__spacefast/crons.json` derives each entry's key from its path; the
|
|
98
|
+
* schedule is never normalized.
|
|
99
|
+
*/
|
|
100
|
+
crons?: {
|
|
101
|
+
path: string;
|
|
102
|
+
schedule: string;
|
|
103
|
+
}[];
|
|
70
104
|
};
|
|
71
105
|
export type EffectiveConfigV1 = {
|
|
72
106
|
version: 1;
|
|
@@ -88,15 +122,15 @@ export type EffectiveConfigV1 = {
|
|
|
88
122
|
headers?: SfConfigV1["headers"];
|
|
89
123
|
metadata?: SfConfigV1["metadata"];
|
|
90
124
|
substitute?: SfConfigV1["substitute"];
|
|
125
|
+
crons?: SfConfigV1["crons"];
|
|
91
126
|
grants?: Grant[];
|
|
92
127
|
};
|
|
93
128
|
/**
|
|
94
129
|
* Config-shape problems use the `config_*` codes; a bad routing rule reports
|
|
95
|
-
* the same code the `_redirects` / `_headers` compiler would give it
|
|
96
|
-
* it is the same grammar and the same compiler.
|
|
130
|
+
* the same code the `_redirects` / `_headers` compiler would give it.
|
|
97
131
|
*/
|
|
98
132
|
export type SfConfigV1Issue = {
|
|
99
|
-
code: "config_alias" | "config_conflict" | "config_identity_moved" | "config_invalid" | "config_key_removed" | "config_unknown_key" | "header_basic_auth_unsupported" | "header_cache_control_platform_managed" | "header_cdn_cache_unsupported" | "header_name_invalid" | "header_name_unsupported" | "header_path_invalid" | "header_pattern_invalid" | "header_port_unsupported" | "header_value_invalid" | "redirect_cache_directive_invalid" | "redirect_cache_not_proxy" | "redirect_destination_invalid" | "redirect_destination_missing" | "redirect_host_invalid" | "redirect_loop_invalid" | "redirect_pattern_invalid" | "redirect_rewrite_destination_invalid" | "redirect_source_invalid" | "redirect_status_unsupported" | "redirect_status_use_rewrites" | "serve_index_required" | "template_syntax_retired";
|
|
133
|
+
code: "config_alias" | "config_conflict" | "config_cron_duplicate_path" | "config_cron_invalid_path" | "config_cron_invalid_schedule" | "config_cron_too_many" | "config_identity_moved" | "config_invalid" | "config_key_removed" | "config_unknown_key" | "header_basic_auth_unsupported" | "header_cache_control_platform_managed" | "header_cdn_cache_unsupported" | "header_name_invalid" | "header_name_unsupported" | "header_path_invalid" | "header_pattern_invalid" | "header_port_unsupported" | "header_value_invalid" | "redirect_cache_directive_invalid" | "redirect_cache_not_proxy" | "redirect_destination_invalid" | "redirect_destination_missing" | "redirect_host_invalid" | "redirect_loop_invalid" | "redirect_pattern_invalid" | "redirect_query_match_invalid" | "redirect_rewrite_destination_invalid" | "redirect_source_invalid" | "redirect_status_unsupported" | "redirect_status_use_rewrites" | "serve_index_required" | "template_syntax_retired";
|
|
100
134
|
severity: "error" | "warning";
|
|
101
135
|
path: string;
|
|
102
136
|
line: number;
|
package/dist/contracts/slugs.js
CHANGED
|
@@ -2,10 +2,19 @@ import { z } from "zod";
|
|
|
2
2
|
export const slugResourceKindValues = ["team", "space"];
|
|
3
3
|
export const slugResourceKind = z.enum(slugResourceKindValues);
|
|
4
4
|
export const slugAvailabilityQuerySchema = z.object({
|
|
5
|
-
kind: slugResourceKind,
|
|
6
|
-
slug: z
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
kind: slugResourceKind.describe("Which kind of slug to check: a space slug or a team slug."),
|
|
6
|
+
slug: z
|
|
7
|
+
.string()
|
|
8
|
+
.default("")
|
|
9
|
+
.describe("Slug to check. It is normalized first, and the verdict describes the normalized form."),
|
|
10
|
+
currentSlug: z
|
|
11
|
+
.string()
|
|
12
|
+
.optional()
|
|
13
|
+
.describe("The resource's current slug, when renaming. A slug that normalizes to this one stays available instead of colliding with itself."),
|
|
14
|
+
teamId: z
|
|
15
|
+
.string()
|
|
16
|
+
.optional()
|
|
17
|
+
.describe("Team the space would belong to. Space slugs and their managed hostnames are checked inside that team; ignored for `kind=team`."),
|
|
9
18
|
});
|
|
10
19
|
export const slugAvailabilityResponseSchema = z.object({
|
|
11
20
|
kind: slugResourceKind.describe("Resource kind the slug was checked for."),
|