@spacefast/common 0.0.12 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/dist/agents/client-registry.d.ts +22 -0
  2. package/dist/agents/client-registry.js +41 -0
  3. package/dist/agents/connect-targets.d.ts +51 -6
  4. package/dist/agents/connect-targets.js +93 -28
  5. package/dist/brand.d.ts +0 -11
  6. package/dist/brand.js +0 -20
  7. package/dist/config/domains.d.ts +15 -6
  8. package/dist/config/domains.js +24 -10
  9. package/dist/config/postgres-budget.d.ts +3 -0
  10. package/dist/config/postgres-budget.js +6 -1
  11. package/dist/config/postgres-budget.json +2 -1
  12. package/dist/contracts/abuse.js +1 -1
  13. package/dist/contracts/access.d.ts +486 -1196
  14. package/dist/contracts/access.js +323 -1054
  15. package/dist/contracts/activity.d.ts +1 -1
  16. package/dist/contracts/activity.js +11 -15
  17. package/dist/contracts/api-keys.d.ts +16 -0
  18. package/dist/contracts/api-keys.js +11 -9
  19. package/dist/contracts/archives.d.ts +1 -2
  20. package/dist/contracts/archives.js +15 -17
  21. package/dist/contracts/beta.js +1 -1
  22. package/dist/contracts/builds.js +14 -14
  23. package/dist/contracts/channels.js +2 -2
  24. package/dist/contracts/comments.d.ts +143 -99
  25. package/dist/contracts/comments.js +194 -79
  26. package/dist/contracts/common.d.ts +12 -12
  27. package/dist/contracts/common.js +33 -30
  28. package/dist/contracts/continuation.js +5 -5
  29. package/dist/contracts/countries.js +2 -7
  30. package/dist/contracts/data-source-routes.d.ts +20 -0
  31. package/dist/contracts/data-source-routes.js +15 -0
  32. package/dist/contracts/device-auth.d.ts +13 -9
  33. package/dist/contracts/device-auth.js +12 -12
  34. package/dist/contracts/docs.d.ts +10 -10
  35. package/dist/contracts/domains.js +39 -33
  36. package/dist/contracts/enums.d.ts +4 -14
  37. package/dist/contracts/enums.js +3 -10
  38. package/dist/contracts/error-code-meta.d.ts +122 -56
  39. package/dist/contracts/error-code-meta.js +43 -19
  40. package/dist/contracts/error-codes.d.ts +7 -4
  41. package/dist/contracts/error-codes.js +48 -24
  42. package/dist/contracts/events.d.ts +22 -15
  43. package/dist/contracts/events.js +33 -5
  44. package/dist/contracts/execution.d.ts +238 -0
  45. package/dist/contracts/execution.js +309 -0
  46. package/dist/contracts/feature-lifecycle.d.ts +39 -188
  47. package/dist/contracts/feature-lifecycle.js +52 -196
  48. package/dist/contracts/features.d.ts +13 -115
  49. package/dist/contracts/features.js +5 -35
  50. package/dist/contracts/functions.d.ts +597 -0
  51. package/dist/contracts/functions.js +475 -0
  52. package/dist/contracts/grants.d.ts +1175 -0
  53. package/dist/contracts/grants.js +783 -0
  54. package/dist/contracts/ids.d.ts +7 -5
  55. package/dist/contracts/ids.js +7 -7
  56. package/dist/contracts/internal.js +2 -2
  57. package/dist/contracts/mcp.d.ts +17 -556
  58. package/dist/contracts/mcp.js +9 -103
  59. package/dist/contracts/me.js +3 -4
  60. package/dist/contracts/notifications.d.ts +108 -0
  61. package/dist/contracts/notifications.js +54 -0
  62. package/dist/contracts/oauth-resources.d.ts +22 -5
  63. package/dist/contracts/oauth-resources.js +23 -2
  64. package/dist/contracts/operations.d.ts +0 -48
  65. package/dist/contracts/operations.js +0 -19
  66. package/dist/contracts/pages.d.ts +10 -14
  67. package/dist/contracts/pages.js +17 -21
  68. package/dist/contracts/plan-policy.d.ts +1 -8
  69. package/dist/contracts/plan-policy.js +1 -4
  70. package/dist/contracts/platform.d.ts +78 -30
  71. package/dist/contracts/platform.js +69 -20
  72. package/dist/contracts/problem-document.d.ts +14 -0
  73. package/dist/contracts/problem-document.js +35 -0
  74. package/dist/contracts/push-new.d.ts +41 -2
  75. package/dist/contracts/push-new.js +4 -0
  76. package/dist/contracts/quotas.d.ts +0 -1
  77. package/dist/contracts/quotas.js +0 -5
  78. package/dist/contracts/repository-connections.d.ts +1 -1
  79. package/dist/contracts/resources.d.ts +16 -71
  80. package/dist/contracts/resources.js +13 -16
  81. package/dist/contracts/runtime-api.d.ts +666 -303
  82. package/dist/contracts/runtime-api.js +272 -113
  83. package/dist/contracts/runtime-app.d.ts +168 -0
  84. package/dist/contracts/runtime-app.js +42 -0
  85. package/dist/contracts/runtime-db.d.ts +424 -0
  86. package/dist/contracts/runtime-db.js +108 -0
  87. package/dist/contracts/runtime-storage.d.ts +120 -0
  88. package/dist/contracts/runtime-storage.js +40 -0
  89. package/dist/contracts/sf-config-v1.d.ts +54 -1
  90. package/dist/contracts/sf-config-v1.js +2 -2
  91. package/dist/contracts/sites.d.ts +6 -0
  92. package/dist/contracts/sites.js +30 -11
  93. package/dist/contracts/space-config.d.ts +91 -121
  94. package/dist/contracts/space-config.js +464 -42
  95. package/dist/contracts/spaces.d.ts +300 -171
  96. package/dist/contracts/spaces.js +128 -98
  97. package/dist/contracts/superadmin-emails.d.ts +2 -2
  98. package/dist/contracts/superadmin-spaces.d.ts +26 -130
  99. package/dist/contracts/superadmin-spaces.js +22 -0
  100. package/dist/contracts/superadmin-tenants.js +4 -4
  101. package/dist/contracts/superadmin.d.ts +4 -0
  102. package/dist/contracts/superadmin.js +14 -1
  103. package/dist/contracts/tags.d.ts +6 -6
  104. package/dist/contracts/tags.js +1 -1
  105. package/dist/contracts/teams.d.ts +9 -9
  106. package/dist/contracts/teams.js +25 -16
  107. package/dist/contracts/theme-json.js +1 -1
  108. package/dist/contracts/transfers.d.ts +0 -1
  109. package/dist/contracts/transfers.js +4 -4
  110. package/dist/contracts/variables.js +3 -3
  111. package/dist/contracts/zero.d.ts +384 -596
  112. package/dist/contracts/zero.js +167 -299
  113. package/dist/dashboard-paths/index.d.ts +18 -3
  114. package/dist/dashboard-paths/index.js +19 -0
  115. package/dist/docs/agent-handoff-document.d.ts +2 -2
  116. package/dist/docs/agent-handoff-document.js +8 -7
  117. package/dist/docs/agent-prose.d.ts +22 -3
  118. package/dist/docs/agent-prose.js +227 -55
  119. package/dist/docs/agent-setup.d.ts +14 -11
  120. package/dist/docs/agent-setup.js +289 -61
  121. package/dist/docs/agent-solutions.d.ts +6 -6
  122. package/dist/docs/agent-solutions.js +24 -22
  123. package/dist/docs/catalog.d.ts +53 -98
  124. package/dist/docs/catalog.js +90 -117
  125. package/dist/docs/error-docs.js +304 -236
  126. package/dist/docs/skill-distribution.d.ts +2 -0
  127. package/dist/docs/skill-distribution.js +7 -4
  128. package/dist/docs/skills.d.ts +546 -0
  129. package/dist/docs/skills.js +340 -0
  130. package/dist/utils/auth-redirect.d.ts +1 -3
  131. package/dist/utils/auth-redirect.js +1 -21
  132. package/dist/utils/browser-credential.d.ts +19 -0
  133. package/dist/utils/browser-credential.js +62 -0
  134. package/dist/utils/build-settings.d.ts +2 -0
  135. package/dist/utils/build-settings.js +61 -9
  136. package/dist/utils/comment-avatars.d.ts +7 -0
  137. package/dist/utils/comment-avatars.js +42 -0
  138. package/dist/utils/content-type.d.ts +3 -3
  139. package/dist/utils/content-type.js +38 -61
  140. package/dist/utils/credential-policy.d.ts +1 -1
  141. package/dist/utils/credential-policy.js +4 -0
  142. package/dist/utils/domain-diagnostics.d.ts +5 -5
  143. package/dist/utils/domain-diagnostics.js +21 -10
  144. package/dist/utils/egress-policy.fixtures.json +1 -1
  145. package/dist/utils/grants.d.ts +53 -0
  146. package/dist/utils/grants.js +160 -0
  147. package/dist/utils/local-space-state.d.ts +78 -4
  148. package/dist/utils/local-space-state.js +384 -82
  149. package/dist/utils/one-shot-replay.d.ts +14 -0
  150. package/dist/utils/one-shot-replay.js +21 -0
  151. package/dist/utils/page-preview.d.ts +7 -0
  152. package/dist/utils/page-preview.js +9 -0
  153. package/dist/utils/pages.d.ts +2 -5
  154. package/dist/utils/pages.js +64 -33
  155. package/dist/utils/publish-form-data.d.ts +22 -0
  156. package/dist/utils/publish-form-data.js +26 -0
  157. package/dist/utils/publish-policy.d.ts +34 -4
  158. package/dist/utils/publish-policy.js +149 -62
  159. package/dist/utils/query-keys.d.ts +8 -10
  160. package/dist/utils/query-keys.js +14 -10
  161. package/dist/utils/runtime-paths.d.ts +3 -0
  162. package/dist/utils/runtime-paths.js +7 -0
  163. package/dist/utils/secure-local-file.d.ts +73 -0
  164. package/dist/utils/secure-local-file.js +1373 -0
  165. package/dist/utils/space-config.d.ts +17 -4
  166. package/dist/utils/space-config.js +151 -8
  167. package/dist/utils/static-runtime-policy.d.ts +5 -0
  168. package/dist/utils/static-runtime-policy.js +54 -10
  169. package/dist/utils/storage-policy.d.ts +20 -0
  170. package/dist/utils/storage-policy.fixtures.json +174 -0
  171. package/dist/utils/storage-policy.js +193 -0
  172. package/dist/utils/upload-session.d.ts +15 -1
  173. package/dist/utils/upload-session.js +68 -2
  174. package/dist/utils/version-file-browser.d.ts +13 -0
  175. package/dist/utils/version-file-browser.js +59 -0
  176. package/package.json +20 -1
  177. package/dist/contracts/mounts.d.ts +0 -142
  178. package/dist/contracts/mounts.js +0 -56
  179. package/dist/utils/access-grant.d.ts +0 -14
  180. package/dist/utils/access-grant.js +0 -88
  181. package/dist/utils/access-match.d.ts +0 -46
  182. package/dist/utils/access-match.fixtures.json +0 -513
  183. package/dist/utils/access-match.js +0 -312
  184. package/dist/utils/access-verdict.fixtures.json +0 -421
  185. package/dist/utils/asset-fingerprint.d.ts +0 -53
  186. package/dist/utils/asset-fingerprint.js +0 -574
  187. package/dist/utils/sf-config-v1.d.ts +0 -2
  188. package/dist/utils/sf-config-v1.fixtures.json +0 -9
  189. package/dist/utils/sf-config-v1.js +0 -551
@@ -1,312 +0,0 @@
1
- // The ONE TS implementation of the runtime's grant-satisfaction kernel
2
- // (internal-docs/access-plan.html X-9): glob-aware `grants ∩ requiredGrants`
3
- // intersection plus signing-key grant-namespace filtering. The PHP evaluator
4
- // (runtime/engine/runtime/access-rules.php `_stattic_unified_grants_intersect`
5
- // / `_stattic_unified_filter_grants_by_namespace`) is the enforcer of record;
6
- // this matcher exists so the cloud's authorize pre-flight (and, later,
7
- // `access simulate`) never mints a token the runtime would reject.
8
- //
9
- // Parity is pinned by a shared JSON corpus (`access-match.fixtures.json`),
10
- // asserted against this module in packages/common and against the PHP in the
11
- // control plane's php-policy-parity test — the one sanctioned
12
- // generated↔source drift-guard pattern. Do not change semantics here without
13
- // extending the corpus.
14
- // Drops every grant not prefixed by one of the signing key's namespaces. This
15
- // bounds a leaked external key's blast radius to exactly the grant namespaces
16
- // the owner pointed it at (and bounds the runtime-local pw: key to `pw:`).
17
- export function filterGrantsByNamespace(grants, namespaces) {
18
- const kept = [];
19
- for (const grant of grants) {
20
- if (typeof grant !== "string" || grant === "") {
21
- continue;
22
- }
23
- for (const namespace of namespaces) {
24
- if (typeof namespace === "string" && namespace !== "" && grant.startsWith(namespace)) {
25
- kept.push(grant);
26
- break;
27
- }
28
- }
29
- }
30
- return kept;
31
- }
32
- // `*` in a requiredGrant matches any run of characters (grants have no path
33
- // structure to anchor on, unlike paths). Exact match when no `*` present.
34
- export function grantGlobMatches(pattern, grant) {
35
- if (!pattern.includes("*")) {
36
- return pattern === grant;
37
- }
38
- const regex = pattern
39
- .split("*")
40
- .map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
41
- .join(".*");
42
- return new RegExp(`^${regex}$`).test(grant);
43
- }
44
- // Glob-aware intersection: a visitor passes when ANY verified concrete grant
45
- // matches ANY requiredGrant. requiredGrants may carry `*` wildcards (e.g.
46
- // "email:*@acme.com"); verified grants are concrete.
47
- export function grantsIntersect(grants, requiredGrants) {
48
- for (const required of requiredGrants) {
49
- if (typeof required !== "string" || required === "") {
50
- continue;
51
- }
52
- for (const grant of grants) {
53
- if (typeof grant !== "string" || grant === "") {
54
- continue;
55
- }
56
- if (grantGlobMatches(required, grant)) {
57
- return true;
58
- }
59
- }
60
- }
61
- return false;
62
- }
63
- // Managed reviewer rules are identity bindings. Policies compiled before the
64
- // identity-only cutover may still contain a generic `space:` grant beside the
65
- // reviewer's email. Treating that legacy entry as another ANY-OF alternative
66
- // recreates the cross-reviewer bypass, so every evaluator derives the effective
67
- // requirement from the trusted managed-block owner before intersecting.
68
- export function requiredGrantsForRule(rule) {
69
- const requiredGrants = rule.auth?.requiredGrants ?? [];
70
- if (rule.managedBy !== "cast_reviewer") {
71
- return requiredGrants;
72
- }
73
- return requiredGrants.filter((grant) => grant.startsWith("email:"));
74
- }
75
- // The composed satisfaction test the authorize pre-flight runs: namespace-drop
76
- // the visitor's grants by the signing key, then intersect with the rule's
77
- // requiredGrants — exactly what the runtime does after verifying a signature.
78
- export function grantsSatisfyRule(input) {
79
- return grantsIntersect(filterGrantsByNamespace(input.grants, input.grantNamespaces), input.requiredGrants);
80
- }
81
- // ---------------------------------------------------------------------------
82
- // Rule-match evaluation (the `match` half of the kernel)
83
- // ---------------------------------------------------------------------------
84
- //
85
- // TS mirror of the PHP `_stattic_unified_rule_matches` /
86
- // `_stattic_unified_path_glob_matches` / `_stattic_unified_ip_in_cidr` family
87
- // (runtime/engine/runtime/access-rules.php). Powers `access simulate` and the
88
- // authorize pre-flight's path scoping. Parity is pinned by the same shared
89
- // corpus (`access-match.fixtures.json`, sections `pathGlob` + `cidr`) asserted
90
- // against the PHP in php-policy-parity.test.ts.
91
- // Mirrors `_spacefast_canonicalize_host`.
92
- export function canonicalizeHost(host) {
93
- return host.trim().toLowerCase().replace(/\.+$/, "");
94
- }
95
- export function hostGlobMatches(pattern, host) {
96
- const regex = pattern
97
- .split("*")
98
- .map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
99
- .join(".*");
100
- return new RegExp(`^${regex}$`, "i").test(canonicalizeHost(host));
101
- }
102
- export function hostTemplateMatches(template, host) {
103
- let regex = "";
104
- let index = 0;
105
- while (index < template.length) {
106
- const char = template[index];
107
- if (char === "*") {
108
- regex += ".*";
109
- index += 1;
110
- continue;
111
- }
112
- if (char === ":") {
113
- const name = template.slice(index + 1).match(/^[A-Za-z][A-Za-z0-9_]*/)?.[0] ?? "";
114
- if (!name) {
115
- return false;
116
- }
117
- regex += "[^.]+";
118
- index += name.length + 1;
119
- continue;
120
- }
121
- regex += char.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
122
- index += 1;
123
- }
124
- return new RegExp(`^${regex}$`, "i").test(canonicalizeHost(host));
125
- }
126
- // Glob path matcher: "/docs/**" (any depth), "/docs/*" (one segment), exact
127
- // otherwise. Empty pattern matches everything.
128
- export function pathGlobMatches(pattern, path) {
129
- if (pattern === "") {
130
- return true;
131
- }
132
- if (!pattern.includes("*")) {
133
- return pattern === path;
134
- }
135
- let regex = "";
136
- let i = 0;
137
- while (i < pattern.length) {
138
- const char = pattern[i];
139
- if (char === "*") {
140
- if (pattern[i + 1] === "*") {
141
- regex += ".*";
142
- i += 2;
143
- continue;
144
- }
145
- regex += "[^/]*";
146
- i += 1;
147
- continue;
148
- }
149
- regex += char.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
150
- i += 1;
151
- }
152
- return new RegExp(`^${regex}$`).test(path);
153
- }
154
- // Case-insensitive substring match on the user agent; empty needle matches.
155
- export function agentMatches(needle, agent) {
156
- if (needle === "") {
157
- return true;
158
- }
159
- return agent.toLowerCase().includes(needle.toLowerCase());
160
- }
161
- function parseIpv6Groups(raw) {
162
- if (raw === "") {
163
- return [];
164
- }
165
- const groups = [];
166
- for (const part of raw.split(":")) {
167
- if (!/^[0-9a-fA-F]{1,4}$/.test(part)) {
168
- return null;
169
- }
170
- groups.push(Number.parseInt(part, 16));
171
- }
172
- return groups;
173
- }
174
- // inet_pton equivalent: dotted-quad IPv4 or RFC 4291 IPv6 (including "::"
175
- // compression and an embedded IPv4 tail) → bytes, or null when unparseable.
176
- function ipToBytes(ip) {
177
- if (/^\d{1,3}(\.\d{1,3}){3}$/.test(ip)) {
178
- const parts = ip.split(".").map(Number);
179
- if (parts.some((part) => part > 255)) {
180
- return null;
181
- }
182
- return Uint8Array.from(parts);
183
- }
184
- if (!ip.includes(":")) {
185
- return null;
186
- }
187
- let head = ip;
188
- let v4Tail = null;
189
- const lastColon = ip.lastIndexOf(":");
190
- const tail = ip.slice(lastColon + 1);
191
- if (tail.includes(".")) {
192
- const tailBytes = ipToBytes(tail);
193
- if (!tailBytes || tailBytes.length !== 4) {
194
- return null;
195
- }
196
- v4Tail = [...tailBytes];
197
- head = ip.slice(0, lastColon + 1) + "0:0"; // placeholder groups, replaced below
198
- }
199
- const doubleColonSplits = head.split("::");
200
- if (doubleColonSplits.length > 2) {
201
- return null;
202
- }
203
- let groups;
204
- if (doubleColonSplits.length === 2) {
205
- const left = parseIpv6Groups(doubleColonSplits[0] ?? "");
206
- const right = parseIpv6Groups(doubleColonSplits[1] ?? "");
207
- if (left === null || right === null || left.length + right.length > 8) {
208
- return null;
209
- }
210
- groups = [...left, ...Array(8 - left.length - right.length).fill(0), ...right];
211
- }
212
- else {
213
- groups = parseIpv6Groups(head);
214
- if (groups === null || groups.length !== 8) {
215
- return null;
216
- }
217
- }
218
- const bytes = new Uint8Array(16);
219
- groups.forEach((group, index) => {
220
- bytes[index * 2] = group >> 8;
221
- bytes[index * 2 + 1] = group & 0xff;
222
- });
223
- if (v4Tail) {
224
- bytes[12] = v4Tail[0];
225
- bytes[13] = v4Tail[1];
226
- bytes[14] = v4Tail[2];
227
- bytes[15] = v4Tail[3];
228
- }
229
- return bytes;
230
- }
231
- // Mirrors `_stattic_unified_ip_in_cidr`: a bare address (no "/") is an exact
232
- // string compare; mixed families never match; malformed input never matches.
233
- export function ipInCidr(ip, cidr) {
234
- if (cidr === "") {
235
- return false;
236
- }
237
- if (!cidr.includes("/")) {
238
- return ip === cidr;
239
- }
240
- const [subnet = "", bitsRaw = ""] = cidr.split("/", 2);
241
- const ipBytes = ipToBytes(ip);
242
- const subnetBytes = ipToBytes(subnet);
243
- if (!ipBytes || !subnetBytes || ipBytes.length !== subnetBytes.length) {
244
- return false;
245
- }
246
- if (!/^\d+$/.test(bitsRaw)) {
247
- return false;
248
- }
249
- const bits = Number.parseInt(bitsRaw, 10);
250
- const maxBits = ipBytes.length * 8;
251
- if (bits < 0 || bits > maxBits) {
252
- return false;
253
- }
254
- const fullBytes = Math.floor(bits / 8);
255
- for (let index = 0; index < fullBytes; index += 1) {
256
- if (ipBytes[index] !== subnetBytes[index]) {
257
- return false;
258
- }
259
- }
260
- const remainder = bits % 8;
261
- if (remainder === 0) {
262
- return true;
263
- }
264
- const mask = (0xff << (8 - remainder)) & 0xff;
265
- return (ipBytes[fullBytes] & mask) === (subnetBytes[fullBytes] & mask);
266
- }
267
- export function ipInAnyCidr(ip, cidrs) {
268
- if (ip === "") {
269
- return false;
270
- }
271
- return cidrs.some((cidr) => typeof cidr === "string" && ipInCidr(ip, cidr));
272
- }
273
- // AND-combined match — mirrors `_stattic_unified_rule_matches` exactly. An
274
- // empty match matches everything in scope.
275
- export function ruleMatchApplies(match, context) {
276
- if (match.host !== undefined && canonicalizeHost(match.host) !== canonicalizeHost(context.host)) {
277
- return false;
278
- }
279
- if (match.hostPattern !== undefined && !hostGlobMatches(match.hostPattern, context.host)) {
280
- return false;
281
- }
282
- if (match.hostTemplate !== undefined && !hostTemplateMatches(match.hostTemplate, context.host)) {
283
- return false;
284
- }
285
- if (match.pathPattern !== undefined && !pathGlobMatches(match.pathPattern, context.path)) {
286
- return false;
287
- }
288
- if (match.channel !== undefined && match.channel !== (context.channel ?? "")) {
289
- return false;
290
- }
291
- if (match.ipCidrs !== undefined && !ipInAnyCidr(context.ip ?? "", match.ipCidrs)) {
292
- return false;
293
- }
294
- if (match.agent !== undefined && !agentMatches(match.agent, context.agent ?? "")) {
295
- return false;
296
- }
297
- if (match.country !== undefined && match.country.toUpperCase() !== (context.country ?? "")) {
298
- return false;
299
- }
300
- if (match.countryNotIn !== undefined &&
301
- match.countryNotIn.some((country) => country.toUpperCase() === (context.country ?? "").toUpperCase())) {
302
- return false;
303
- }
304
- if (match.header !== undefined) {
305
- const name = match.header.name.toLowerCase();
306
- const actual = Object.entries(context.headers ?? {}).find(([key]) => key.toLowerCase() === name)?.[1];
307
- if (match.header.name === "" || (actual ?? "") !== match.header.value) {
308
- return false;
309
- }
310
- }
311
- return true;
312
- }