@spacefast/common 0.0.24 → 0.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/brand-assets/LICENSE-Haskoy.txt +93 -0
  2. package/brand-assets/haskoy-latin-variable.woff2 +0 -0
  3. package/brand-assets/spacefast-favicon.svg +4 -4
  4. package/brand-assets/spacefast-sf-full-bleed.svg +3 -3
  5. package/brand-assets/spacefast-wordmark.svg +2 -4
  6. package/dist/agents/connect-targets.js +1 -1
  7. package/dist/agents/private-key-oauth.d.ts +0 -1
  8. package/dist/agents/private-key-oauth.js +46 -63
  9. package/dist/brand-assets-build.js +4 -6
  10. package/dist/brand-assets.d.ts +5 -15
  11. package/dist/brand-assets.js +15 -14
  12. package/dist/config/domains.d.ts +47 -7
  13. package/dist/config/domains.js +65 -10
  14. package/dist/contracts/access.d.ts +3 -3
  15. package/dist/contracts/activity.d.ts +1 -1
  16. package/dist/contracts/activity.js +5 -3
  17. package/dist/contracts/api-keys.js +2 -2
  18. package/dist/contracts/billing.d.ts +2 -1
  19. package/dist/contracts/billing.js +30 -0
  20. package/dist/contracts/builds.d.ts +34 -22
  21. package/dist/contracts/builds.js +18 -6
  22. package/dist/contracts/channels.js +1 -1
  23. package/dist/contracts/comments.d.ts +1 -1
  24. package/dist/contracts/common.d.ts +6 -6
  25. package/dist/contracts/common.js +5 -5
  26. package/dist/contracts/crons.d.ts +35 -0
  27. package/dist/contracts/crons.js +42 -0
  28. package/dist/contracts/device-auth.js +1 -1
  29. package/dist/contracts/docs.d.ts +5 -5
  30. package/dist/contracts/docs.js +2 -2
  31. package/dist/contracts/domains.d.ts +74 -63
  32. package/dist/contracts/domains.js +29 -2
  33. package/dist/contracts/enums.d.ts +3 -2
  34. package/dist/contracts/enums.js +10 -10
  35. package/dist/contracts/error-code-meta.d.ts +14 -0
  36. package/dist/contracts/error-code-meta.js +17 -0
  37. package/dist/contracts/error-codes.d.ts +1 -1
  38. package/dist/contracts/error-codes.js +4 -1
  39. package/dist/contracts/execution.d.ts +15 -12
  40. package/dist/contracts/execution.js +15 -12
  41. package/dist/contracts/feature-lifecycle.d.ts +4 -14
  42. package/dist/contracts/feature-lifecycle.js +0 -11
  43. package/dist/contracts/features.d.ts +33 -47
  44. package/dist/contracts/features.js +27 -20
  45. package/dist/contracts/functions.d.ts +169 -2
  46. package/dist/contracts/functions.js +160 -4
  47. package/dist/contracts/git.d.ts +27 -33
  48. package/dist/contracts/git.js +10 -11
  49. package/dist/contracts/grants.d.ts +2 -2
  50. package/dist/contracts/ids.js +2 -2
  51. package/dist/contracts/internal.d.ts +5 -16
  52. package/dist/contracts/internal.js +2 -12
  53. package/dist/contracts/mcp.d.ts +11 -0
  54. package/dist/contracts/mcp.js +5 -0
  55. package/dist/contracts/me.js +1 -1
  56. package/dist/contracts/operations.d.ts +4 -4
  57. package/dist/contracts/operations.js +2 -2
  58. package/dist/contracts/pages.d.ts +6 -6
  59. package/dist/contracts/plan-policy.d.ts +1 -1
  60. package/dist/contracts/plan-policy.js +1 -1
  61. package/dist/contracts/platform.d.ts +4 -4
  62. package/dist/contracts/publish-archive.d.ts +170 -160
  63. package/dist/contracts/publish-archive.js +8 -1
  64. package/dist/contracts/push-new.d.ts +4 -4
  65. package/dist/contracts/quotas.js +2 -2
  66. package/dist/contracts/repository-connections.d.ts +43 -30
  67. package/dist/contracts/repository-connections.js +11 -3
  68. package/dist/contracts/resources.d.ts +8 -8
  69. package/dist/contracts/resources.js +6 -6
  70. package/dist/contracts/runtime-api.d.ts +103 -56
  71. package/dist/contracts/runtime-api.js +67 -26
  72. package/dist/contracts/runtime-app.d.ts +2 -2
  73. package/dist/contracts/runtime-db.d.ts +6 -6
  74. package/dist/contracts/runtime-db.js +2 -2
  75. package/dist/contracts/runtime-purge.d.ts +8 -0
  76. package/dist/contracts/runtime-purge.js +7 -0
  77. package/dist/contracts/runtime-storage.d.ts +3 -2
  78. package/dist/contracts/runtime-storage.js +2 -1
  79. package/dist/contracts/sf-config-v1.d.ts +48 -10
  80. package/dist/contracts/space-config.d.ts +60 -3
  81. package/dist/contracts/space-config.js +213 -18
  82. package/dist/contracts/spaces.d.ts +55 -74
  83. package/dist/contracts/spaces.js +11 -14
  84. package/dist/contracts/superadmin-spaces.d.ts +9 -9
  85. package/dist/contracts/superadmin-teams.d.ts +2 -2
  86. package/dist/contracts/superadmin-tenants.d.ts +0 -6
  87. package/dist/contracts/superadmin-tenants.js +1 -7
  88. package/dist/contracts/superadmin.d.ts +135 -22
  89. package/dist/contracts/superadmin.js +43 -12
  90. package/dist/contracts/tags.d.ts +21 -21
  91. package/dist/contracts/tags.js +3 -3
  92. package/dist/contracts/teams.d.ts +14 -17
  93. package/dist/contracts/teams.js +6 -6
  94. package/dist/contracts/transfers.js +2 -2
  95. package/dist/contracts/variables.d.ts +4 -4
  96. package/dist/contracts/variables.js +3 -3
  97. package/dist/contracts/webhooks.d.ts +4 -4
  98. package/dist/contracts/zero.d.ts +15 -17
  99. package/dist/contracts/zero.js +12 -12
  100. package/dist/docs/agent-prose.d.ts +1 -1
  101. package/dist/docs/agent-prose.js +11 -14
  102. package/dist/docs/agent-setup.js +5 -2
  103. package/dist/docs/catalog.d.ts +7 -7
  104. package/dist/docs/catalog.js +7 -7
  105. package/dist/docs/error-docs.js +145 -133
  106. package/dist/docs/skills.d.ts +12 -12
  107. package/dist/docs/skills.js +4 -4
  108. package/dist/test-helpers/fetch-stub.js +1 -0
  109. package/dist/utils/build-settings.d.ts +5 -1
  110. package/dist/utils/build-settings.js +82 -10
  111. package/dist/utils/canonical-json.js +1 -0
  112. package/dist/utils/concurrency.js +1 -0
  113. package/dist/utils/credential-policy.js +4 -3
  114. package/dist/utils/dns-instructions.js +9 -9
  115. package/dist/utils/error-code.js +1 -0
  116. package/dist/utils/grant-decision.fixtures.json +2 -2
  117. package/dist/utils/grants.js +3 -1
  118. package/dist/utils/local-space-state.d.ts +8 -11
  119. package/dist/utils/local-space-state.js +13 -24
  120. package/dist/utils/one-shot-replay.d.ts +4 -1
  121. package/dist/utils/page-colors.d.ts +14 -12
  122. package/dist/utils/page-colors.js +15 -13
  123. package/dist/utils/page-fonts.d.ts +1 -1
  124. package/dist/utils/page-fonts.js +11 -18
  125. package/dist/utils/pages.d.ts +20 -1
  126. package/dist/utils/pages.js +22 -9
  127. package/dist/utils/publish-policy.d.ts +7 -0
  128. package/dist/utils/publish-policy.fixtures.json +11 -5
  129. package/dist/utils/publish-policy.js +9 -1
  130. package/dist/utils/query-keys.d.ts +4 -4
  131. package/dist/utils/query-keys.js +2 -2
  132. package/dist/utils/runtime-upload.d.ts +5 -0
  133. package/dist/utils/runtime-upload.js +7 -0
  134. package/dist/utils/secure-local-file.js +5 -16
  135. package/dist/utils/space-config.d.ts +1 -1
  136. package/dist/utils/space-config.js +3 -0
  137. package/dist/utils/static-runtime-policy.d.ts +9 -3
  138. package/dist/utils/static-runtime-policy.fixtures.json +38 -41
  139. package/dist/utils/static-runtime-policy.js +22 -56
  140. package/dist/utils/upload-session.d.ts +4 -1
  141. package/dist/utils/upload-session.js +33 -5
  142. package/dist/utils/version-path.js +1 -1
  143. package/dist/vocabulary.d.ts +8 -8
  144. package/dist/vocabulary.js +31 -20
  145. package/package.json +2 -17
@@ -1,44 +1,33 @@
1
1
  {
2
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 }
3
+ {
4
+ "path": "index.php",
5
+ "expected": true
6
+ },
7
+ {
8
+ "path": "nested/app.phtml",
9
+ "expected": true
10
+ },
11
+ {
12
+ "path": "lib.phar",
13
+ "expected": true
14
+ },
15
+ {
16
+ "path": "legacy.php5",
17
+ "expected": true
18
+ },
19
+ {
20
+ "path": "index.html",
21
+ "expected": false
22
+ },
23
+ {
24
+ "path": "assets/main.js",
25
+ "expected": false
26
+ },
27
+ {
28
+ "path": ".env",
29
+ "expected": false
30
+ }
42
31
  ],
43
32
  "safeContentType": [
44
33
  {
@@ -46,12 +35,20 @@
46
35
  "mime": "application/x-httpd-php",
47
36
  "expected": "text/plain; charset=utf-8"
48
37
  },
49
- { "path": "lib.phar", "mime": "application/zip", "expected": "application/octet-stream" },
38
+ {
39
+ "path": "lib.phar",
40
+ "mime": "application/zip",
41
+ "expected": "application/octet-stream"
42
+ },
50
43
  {
51
44
  "path": "assets/main.js",
52
45
  "mime": "text/javascript; charset=utf-8",
53
46
  "expected": "text/javascript; charset=utf-8"
54
47
  },
55
- { "path": "logo.svg", "mime": "image/svg+xml", "expected": "image/svg+xml" }
48
+ {
49
+ "path": "logo.svg",
50
+ "mime": "image/svg+xml",
51
+ "expected": "image/svg+xml"
52
+ }
56
53
  ]
57
54
  }
@@ -1,5 +1,5 @@
1
1
  // Single source of truth for static-runtime content policy: PHP-like inert
2
- // classification, immutable-asset detection, and safe content-type forcing.
2
+ // classification and safe content-type forcing.
3
3
  //
4
4
  // This module is intentionally pure (no node:path, no I/O) so the exact same
5
5
  // rules can be mechanically code-generated into the PHP runtime (runtime
@@ -30,7 +30,7 @@ export const INTERNAL_REDIRECT_RESPONSE_HEADERS = [
30
30
  "x-reproxy-url",
31
31
  "x-sendfile",
32
32
  ];
33
- // Rejected/platform-managed response headers (internal-docs/platform.md "Routing And
33
+ // Rejected/platform-managed response headers (the platform spec "Routing And
34
34
  // Headers"): user `_headers` rules can never set or remove these. The
35
35
  // internal-redirect/sendfile family above is spread in, so it stays a strict subset —
36
36
  // anything the proxy lane refuses to relay is also refused from `_headers`. The rest is
@@ -87,52 +87,27 @@ export function isPlatformManagedResponseHeader(name) {
87
87
  return (PLATFORM_MANAGED_RESPONSE_HEADER_SET.has(lower) ||
88
88
  PLATFORM_MANAGED_RESPONSE_HEADER_PREFIXES.some((prefix) => lower.startsWith(prefix)));
89
89
  }
90
- export const NON_IMMUTABLE_EXTENSIONS = ["html", "htm", "php", "txt", "xml"];
91
- const PHP_LIKE_EXTENSION_SET = new Set(PHP_LIKE_EXTENSIONS);
92
- const NON_IMMUTABLE_EXTENSION_SET = new Set(NON_IMMUTABLE_EXTENSIONS);
93
- // Immutable caching is decided by DETERMINISTIC signals only reserved framework
94
- // build directories below, plus user-declared `_headers` Cache-Control rules that
95
- // override the baked default at serve time. There is deliberately NO filename-entropy
96
- // heuristic: an 8-char base64url bundler hash is character-for-character
97
- // indistinguishable from a short human name (D3GeoMap, McKayCV2), so any guess either
98
- // pins a user's mutable file for a year (stale site nobody can fix — browsers have no
99
- // bust channel) or silently downgrades real hashes to revalidate-every-load, which
100
- // under the wp.cloud edge per-IP rate limiter turned dashboard page loads into 429
101
- // storms (2026-07-06). Unrecognized files default to the safe direction:
102
- // `max-age=0, must-revalidate` for browsers, long s-maxage + purge-on-publish at the
103
- // edge.
104
- //
105
- // Each prefix is HIGH-CONFIDENCE guaranteed-hashed:
106
- // - `_next/static/` Next.js immutable build assets (chunks/css/media), all
107
- // [contenthash]; Next itself serves this dir with `immutable`.
108
- // - `_app/immutable/` SvelteKit (Vite) — the directory is literally named `immutable`
109
- // and holds only fingerprinted chunks/assets.
110
- // - `_nuxt/` Nuxt build dir — Vite-hashed client bundle, served from a
111
- // reserved app-owned path.
112
- // - `_astro/` Astro bundled assets — all content-hashed.
113
- //
114
- // DELIBERATELY EXCLUDED: generic user-writable dirs (Vite's `assets/`, CRA/Gatsby's
115
- // `static/`). Users drop NON-hashed files there, so widening to them would create
116
- // year-long false positives. Deployments of bundler output declare those dirs immutable
117
- // themselves via a `_headers` rule (e.g. `/assets/*` → `Cache-Control: public,
118
- // max-age=31536000, immutable`), which the publisher — a build we ran, an agent, a CI
119
- // deploy — writes because it KNOWS the output is content-hashed.
120
- export const GUARANTEED_IMMUTABLE_PREFIXES = [
121
- "_next/static/",
122
- "_app/immutable/",
123
- "_nuxt/",
124
- "_astro/",
125
- ];
126
- /** True when the path lives under a framework dir where every emitted asset is content-hashed. */
127
- function isUnderGuaranteedImmutablePrefix(filePath) {
128
- const normalized = filePath.startsWith("/") ? filePath.slice(1) : filePath;
129
- for (const prefix of GUARANTEED_IMMUTABLE_PREFIXES) {
130
- if (normalized.startsWith(prefix)) {
131
- return true;
132
- }
133
- }
134
- return false;
90
+ /**
91
+ * The token grammar a `_headers` rule accepts for a header NAME. The routing
92
+ * compiler enforces it; anything that GENERATES `_headers` rules (the Next
93
+ * materializer's framework sections) must gate on the same pattern, so a
94
+ * generated rule can never fail the author's publish.
95
+ */
96
+ export const HEADER_RULE_NAME_PATTERN = /^[A-Za-z0-9-]+$/;
97
+ /** `content-type` `Content-Type`: the casing compiled rules and generated `_headers` carry. */
98
+ export function canonicalHeaderName(input) {
99
+ return input
100
+ .trim()
101
+ .toLowerCase()
102
+ .split("-")
103
+ .map((part) => (part ? `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}` : part))
104
+ .join("-");
135
105
  }
106
+ const PHP_LIKE_EXTENSION_SET = new Set(PHP_LIKE_EXTENSIONS);
107
+ // Immutable-asset detection is NOT decided here: `compiled_cache_class` in
108
+ // crates/stattic-runtime-core (responses.rs) is the one implementation, at
109
+ // finalize. A TS re-implementation lived here once, drifted from the
110
+ // enforcer, and was deleted rather than re-synced.
136
111
  function lastSegment(filePath) {
137
112
  const slash = filePath.lastIndexOf("/");
138
113
  return slash >= 0 ? filePath.slice(slash + 1) : filePath;
@@ -152,15 +127,6 @@ export function pathStem(filePath) {
152
127
  export function isPhpLikeStaticPath(filePath) {
153
128
  return PHP_LIKE_EXTENSION_SET.has(pathExtension(filePath));
154
129
  }
155
- export function isImmutableAssetPath(filePath) {
156
- if (NON_IMMUTABLE_EXTENSION_SET.has(pathExtension(filePath))) {
157
- return false;
158
- }
159
- // Path-convention layer: anything under a guaranteed-content-hashed framework build
160
- // dir is immutable regardless of filename. The extension gate above still applies,
161
- // so an `index.html` accidentally under `_next/static/` is never pinned.
162
- return isUnderGuaranteedImmutablePrefix(filePath);
163
- }
164
130
  /** Forced inert serving policy for a committed static file. PHP-like files are never executable. */
165
131
  export function runtimeFileSafety(filePath) {
166
132
  return {
@@ -33,8 +33,10 @@ export declare class UploadTargetError extends Error {
33
33
  readonly target: UploadTarget;
34
34
  readonly status: number;
35
35
  readonly serverError?: UploadTargetServerError | undefined;
36
- constructor(target: UploadTarget, status: number, message: string, serverError?: UploadTargetServerError | undefined);
36
+ readonly retryAfterMs?: number | undefined;
37
+ constructor(target: UploadTarget, status: number, message: string, serverError?: UploadTargetServerError | undefined, retryAfterMs?: number | undefined);
37
38
  }
39
+ export declare function uploadRetryAfterMs(value: string | null, now?: number): number | undefined;
38
40
  export declare function uploadPageHasRemainder(page: UploadSession): boolean;
39
41
  export declare const UPLOAD_STALLED_RESUME_MAX_ATTEMPTS = 3;
40
42
  export declare function uploadQueueAdvanced(before: UploadSession, after: UploadSession | null): boolean;
@@ -42,6 +44,7 @@ export declare function executeUploadSession(input: {
42
44
  session: UploadSession;
43
45
  targets?: readonly UploadTarget[] | undefined;
44
46
  concurrency?: number | undefined;
47
+ settleOnFailure?: boolean | undefined;
45
48
  fetch?: ((...args: Parameters<typeof fetch>) => ReturnType<typeof fetch>) | undefined;
46
49
  prepareTarget?: ((target: UploadTarget) => Promise<UploadTargetBody> | UploadTargetBody) | undefined;
47
50
  onEvent?: ((event: UploadSessionEvent) => void) | undefined;
@@ -2,14 +2,30 @@ export class UploadTargetError extends Error {
2
2
  target;
3
3
  status;
4
4
  serverError;
5
- constructor(target, status, message, serverError) {
5
+ retryAfterMs;
6
+ constructor(target, status, message, serverError, retryAfterMs) {
6
7
  super(message);
7
8
  this.target = target;
8
9
  this.status = status;
9
10
  this.serverError = serverError;
11
+ this.retryAfterMs = retryAfterMs;
10
12
  this.name = "UploadTargetError";
11
13
  }
12
14
  }
15
+ export function uploadRetryAfterMs(value, now = Date.now()) {
16
+ if (!value) {
17
+ return undefined;
18
+ }
19
+ const seconds = Number(value);
20
+ if (Number.isFinite(seconds) && seconds >= 0) {
21
+ return Math.ceil(seconds * 1000);
22
+ }
23
+ const date = Date.parse(value);
24
+ if (!Number.isFinite(date)) {
25
+ return undefined;
26
+ }
27
+ return Math.max(0, date - now);
28
+ }
13
29
  function parseUploadTargetServerError(raw) {
14
30
  let parsed;
15
31
  try {
@@ -73,7 +89,7 @@ export function uploadQueueAdvanced(before, after) {
73
89
  }
74
90
  return after.targets.some((target, index) => target.path !== before.targets[index]?.path);
75
91
  }
76
- async function runConcurrent(items, concurrency, fn) {
92
+ async function runConcurrent(items, concurrency, settleOnFailure, fn) {
77
93
  let nextIndex = 0;
78
94
  const runWorker = async () => {
79
95
  const item = items[nextIndex++];
@@ -83,7 +99,18 @@ async function runConcurrent(items, concurrency, fn) {
83
99
  await fn(item);
84
100
  return runWorker();
85
101
  };
86
- await Promise.all(Array.from({ length: Math.min(Math.max(concurrency, 1), items.length || 1) }).map(() => runWorker()));
102
+ const workers = Array.from({
103
+ length: Math.min(Math.max(concurrency, 1), items.length || 1),
104
+ }).map(() => runWorker());
105
+ if (!settleOnFailure) {
106
+ await Promise.all(workers);
107
+ return;
108
+ }
109
+ const outcomes = await Promise.allSettled(workers);
110
+ const failed = outcomes.find((outcome) => outcome.status === "rejected");
111
+ if (failed) {
112
+ throw failed.reason;
113
+ }
87
114
  }
88
115
  export async function executeUploadSession(input) {
89
116
  const targets = input.targets ?? input.session.targets;
@@ -91,7 +118,8 @@ export async function executeUploadSession(input) {
91
118
  return;
92
119
  }
93
120
  const fetchImpl = input.fetch ?? fetch;
94
- await runConcurrent(targets, input.concurrency ?? 4, async (target) => {
121
+ const settleOnFailure = input.settleOnFailure ?? false;
122
+ await runConcurrent(targets, input.concurrency ?? 4, settleOnFailure, async (target) => {
95
123
  input.onEvent?.({ type: "target-start", target });
96
124
  try {
97
125
  const prepared = input.prepareTarget
@@ -114,7 +142,7 @@ export async function executeUploadSession(input) {
114
142
  const details = await response.text().catch(() => "");
115
143
  const serverError = parseUploadTargetServerError(details);
116
144
  const suffix = details.trim() ? `: ${details.trim().slice(0, 1_000)}` : "";
117
- throw new UploadTargetError(target, response.status, `Upload failed for ${target.path} with ${response.status} ${response.statusText}${suffix}.`, serverError);
145
+ throw new UploadTargetError(target, response.status, `Upload failed for ${target.path} with ${response.status} ${response.statusText}${suffix}.`, serverError, uploadRetryAfterMs(response.headers.get("retry-after")));
118
146
  }
119
147
  input.onEvent?.({ type: "target-done", target });
120
148
  }
@@ -1,4 +1,4 @@
1
- // Canonical object-path form (internal-docs/platform.md "Upload Contract"):
1
+ // Canonical object-path form (the platform spec "Upload Contract"):
2
2
  // UTF-8, Unicode NFC, percent-decoded exactly once. This canonical form is
3
3
  // what manifest paths, finalize's normalized paths, route-map keys, and dedup
4
4
  // keys all mean. The PHP runtime applies the same transform (rawurldecode once
@@ -104,8 +104,8 @@ export declare const CONCEPTS: {
104
104
  readonly id: "infra";
105
105
  readonly canonicalNoun: "infra";
106
106
  readonly aliases: readonly ["infrastructure"];
107
- readonly externalTerms: readonly ["WP.Cloud"];
108
- readonly deprecated: readonly ["code.storage", "Pierre"];
107
+ readonly externalTerms: readonly ["WP Cloud"];
108
+ readonly deprecated: readonly ["code.storage", "Pierre", "the hosting provider"];
109
109
  readonly description: string;
110
110
  };
111
111
  };
@@ -143,10 +143,10 @@ export declare const EXTERNAL_TERM_ALLOWLIST: readonly [{
143
143
  readonly replacement: "space";
144
144
  readonly reason: string;
145
145
  }, {
146
- readonly term: "WP.Cloud";
146
+ readonly term: "WP Cloud";
147
147
  readonly concept: "infra";
148
- readonly allowedContexts: readonly ["platform-api", "fixed-phrase"];
149
- readonly allowedPhrases: readonly ["built on WP.Cloud"];
148
+ readonly allowedContexts: readonly ["fixed-phrase"];
149
+ readonly allowedPhrases: readonly ["the same infra as Automattic, WP Cloud, Pressable, and WordPress.com"];
150
150
  readonly replacement: "infra";
151
151
  readonly reason: string;
152
152
  }];
@@ -208,10 +208,10 @@ export declare const PROVIDER_HYGIENE: {
208
208
  readonly reason: "The build sandbox vendor is never named; it is 'Spacefast Builds'.";
209
209
  };
210
210
  readonly wpcloud: {
211
- readonly internalName: "WP.Cloud";
211
+ readonly internalName: "WP Cloud";
212
212
  readonly replacement: "infra";
213
- readonly allowedContexts: readonly ["platform-api", "fixed-phrase"];
214
- readonly allowedPhrases: readonly ["built on WP.Cloud"];
213
+ readonly allowedContexts: readonly ["fixed-phrase"];
214
+ readonly allowedPhrases: readonly ["the same infra as Automattic, WP Cloud, Pressable, and WordPress.com"];
215
215
  readonly reason: string;
216
216
  };
217
217
  readonly codeStorage: {
@@ -10,7 +10,7 @@
10
10
  //
11
11
  // - `space` is the primitive noun everywhere, user surfaces and platform API
12
12
  // alike. A space IS a site: there is no second host entity to name. `site`
13
- // survives only as WP.Cloud's own word for the box, in operator surfaces
13
+ // survives only as WP Cloud's own word for the box, in operator surfaces
14
14
  // and the warm-pool inventory.
15
15
  // - `publish` is the verb. AMENDED 2026-07-02: `deploy` / `deployments` are
16
16
  // first-class ALIASES of `publish` / `versions` (see DEPLOY_ALIASES) — they
@@ -22,10 +22,14 @@
22
22
  // - `API key` — never "access token".
23
23
  // - `Collab` is the feature; `comment` is the unit.
24
24
  // - `Superpowers` is the page-enhancement feature.
25
- // - Provider names never leak externally: never "E2B" (say "Spacefast
26
- // Builds" / "Spacefast CI"), never "WP.Cloud" (say "infra", except the
27
- // platform API or the fixed phrase "built on WP.Cloud"), never
28
- // "code.storage" / "Pierre" (see PROVIDER_HYGIENE).
25
+ // - Provider names stay off public surfaces by default: never "E2B" (say
26
+ // "Spacefast Builds" / "Spacefast CI"), never "code.storage" / "Pierre".
27
+ // The infra brand is "WP Cloud" never "WP.Cloud"/"wp-cloud" (AMENDED
28
+ // 2026-08-13). Prefer "infra"; when an external reference is genuinely
29
+ // necessary (provider identity fields, domain conflicts), name WP Cloud
30
+ // outright — NEVER the euphemism "the hosting provider". Marketing may use
31
+ // the family line "the same infra as Automattic, WP Cloud, Pressable, and
32
+ // WordPress.com" (see PROVIDER_HYGIENE).
29
33
  export const CONCEPTS = {
30
34
  space: {
31
35
  id: "space",
@@ -102,10 +106,11 @@ export const CONCEPTS = {
102
106
  id: "infra",
103
107
  canonicalNoun: "infra",
104
108
  aliases: ["infrastructure"],
105
- externalTerms: ["WP.Cloud"],
106
- deprecated: ["code.storage", "Pierre"],
107
- description: "The hosting substrate. Say 'infra' externally; 'WP.Cloud' only in the " +
108
- "platform API or the phrase 'built on WP.Cloud'. Never 'code.storage'/'Pierre'.",
109
+ externalTerms: ["WP Cloud"],
110
+ deprecated: ["code.storage", "Pierre", "the hosting provider"],
111
+ description: "The hosting substrate. Prefer 'infra'; when an external reference is " +
112
+ "necessary, name 'WP Cloud' (its real spelling) never the euphemism " +
113
+ "'the hosting provider'. Never 'code.storage'/'Pierre'.",
109
114
  },
110
115
  };
111
116
  export const EXTERNAL_TERM_ALLOWLIST = [
@@ -134,17 +139,21 @@ export const EXTERNAL_TERM_ALLOWLIST = [
134
139
  allowedContexts: ["operator"],
135
140
  replacement: "space",
136
141
  reason: "A space IS a site, so 'site' is no longer a Spacefast noun — it is only " +
137
- "WP.Cloud's word for the box, which operator surfaces and warm-pool " +
142
+ "WP Cloud's word for the box, which operator surfaces and warm-pool " +
138
143
  "inventory may use. Every customer-facing surface says 'space'.",
139
144
  },
140
145
  {
141
- term: "WP.Cloud",
146
+ term: "WP Cloud",
142
147
  concept: "infra",
143
- allowedContexts: ["platform-api", "fixed-phrase"],
144
- allowedPhrases: ["built on WP.Cloud"],
148
+ allowedContexts: ["fixed-phrase"],
149
+ allowedPhrases: ["the same infra as Automattic, WP Cloud, Pressable, and WordPress.com"],
145
150
  replacement: "infra",
146
- reason: "Only the platform API or the exact phrase 'built on WP.Cloud' may name " +
147
- "the provider; general copy says 'infra'.",
151
+ reason: "AMENDED 2026-08-13: prefer 'infra'. Same day: the platform-api " +
152
+ "carve-out is revoked API values say mysql/phpmyadmin/infra, never " +
153
+ "wpcloud. Name WP Cloud (its real spelling — never 'WP.Cloud') only " +
154
+ "where the external reference is necessary: domain-conflict copy and " +
155
+ "the marketing family line in allowedPhrases. Never the euphemism " +
156
+ "'the hosting provider'.",
148
157
  },
149
158
  ];
150
159
  export const DEPLOY_ALIASES = [
@@ -167,12 +176,14 @@ export const PROVIDER_HYGIENE = {
167
176
  reason: "The build sandbox vendor is never named; it is 'Spacefast Builds'.",
168
177
  },
169
178
  wpcloud: {
170
- internalName: "WP.Cloud",
179
+ internalName: "WP Cloud",
171
180
  replacement: "infra",
172
- allowedContexts: ["platform-api", "fixed-phrase"],
173
- allowedPhrases: ["built on WP.Cloud"],
174
- reason: "Hosting substrate; externally 'infra' except the platform API or the " +
175
- "phrase 'built on WP.Cloud'.",
181
+ allowedContexts: ["fixed-phrase"],
182
+ allowedPhrases: ["the same infra as Automattic, WP Cloud, Pressable, and WordPress.com"],
183
+ reason: "Hosting substrate; prefer 'infra' (AMENDED 2026-08-13, same day: the " +
184
+ "platform-api carve-out is revoked — API values say mysql/phpmyadmin/" +
185
+ "infra, never wpcloud). Necessary external references name WP Cloud " +
186
+ "outright — never 'the hosting provider'.",
176
187
  },
177
188
  codeStorage: {
178
189
  internalName: "code.storage",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spacefast/common",
3
- "version": "0.0.24",
3
+ "version": "0.0.26",
4
4
  "license": "MIT",
5
5
  "description": "Shared TypeScript contracts and utilities for Spacefast packages.",
6
6
  "repository": {
@@ -20,22 +20,6 @@
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
- "../cli/skill.template.md",
31
- "../cli/skill.references.template.md",
32
- "../cli/scripts/generate-skill.mjs",
33
- "../../e2e-tests/fixtures/zero-all-features/api-finalize-request.json",
34
- "../../e2e-tests/fixtures/zero-all-features/runtime-compiler-finalize-input.json",
35
- "../../runtime/engine/shared/fonts",
36
- "src/docs/agent-prose.ts"
37
- ]
38
- },
39
23
  "exports": {
40
24
  "./brand": {
41
25
  "types": "./dist/brand.d.ts",
@@ -116,6 +100,7 @@
116
100
  "culori": "^4.0.2",
117
101
  "js-yaml": "^4.1.1",
118
102
  "mime": "^4.1.0",
103
+ "oauth4webapi": "3.8.7",
119
104
  "parse5": "^7.3.0",
120
105
  "smol-toml": "^1.7.0",
121
106
  "zod": "^4.4.3"