anhedral 0.8.5 → 0.9.0

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 (126) hide show
  1. package/README.md +140 -34
  2. package/assets/anhedral-cli-init-technical.svg +8 -8
  3. package/assets/anhedral-cli-init.svg +9 -9
  4. package/assets/security/LICENSES.txt +63 -0
  5. package/assets/security/audit-deps.mjs +295 -0
  6. package/assets/security/braces-regression.mjs +102 -0
  7. package/assets/security/braces@3.0.3.patch +285 -0
  8. package/assets/security/decode-uri-component@0.2.2.patch +149 -0
  9. package/assets/security/decoder-regression.mjs +37 -0
  10. package/assets/security/forge-regression.mjs +46 -0
  11. package/assets/security/manifest.json +53 -0
  12. package/assets/security/node-forge@1.4.0.patch +26 -0
  13. package/dist/access.d.ts +10 -0
  14. package/dist/access.js +93 -0
  15. package/dist/auth-schema-snapshot.d.ts +346 -0
  16. package/dist/auth-schema-snapshot.js +347 -0
  17. package/dist/auth-schema.d.ts +1 -0
  18. package/dist/auth-schema.js +57 -0
  19. package/dist/bin.js +353 -10
  20. package/dist/bounded-file.d.ts +2 -0
  21. package/dist/bounded-file.js +30 -0
  22. package/dist/capabilities.d.ts +19 -33
  23. package/dist/capabilities.js +73 -71
  24. package/dist/cloudflare.d.ts +14 -0
  25. package/dist/cloudflare.js +66 -0
  26. package/dist/command.js +12 -3
  27. package/dist/delivery.d.ts +118 -0
  28. package/dist/delivery.js +611 -0
  29. package/dist/dependencies.d.ts +22 -0
  30. package/dist/dependencies.js +109 -67
  31. package/dist/dependency-order.d.ts +2 -0
  32. package/dist/dependency-order.js +24 -0
  33. package/dist/index.d.ts +18 -1
  34. package/dist/index.js +12 -1
  35. package/dist/managed-hosting.d.ts +49 -0
  36. package/dist/managed-hosting.js +373 -0
  37. package/dist/management.d.ts +3 -0
  38. package/dist/management.js +47 -0
  39. package/dist/platforms/desktop.d.ts +2 -2
  40. package/dist/platforms/desktop.js +22 -12
  41. package/dist/platforms/extension.d.ts +2 -2
  42. package/dist/platforms/extension.js +12 -4
  43. package/dist/platforms/mobile.d.ts +2 -2
  44. package/dist/platforms/mobile.js +13 -7
  45. package/dist/pnpm-policy.d.ts +4 -0
  46. package/dist/pnpm-policy.js +66 -0
  47. package/dist/project-state.d.ts +28 -0
  48. package/dist/project-state.js +226 -0
  49. package/dist/provider-readiness.d.ts +30 -0
  50. package/dist/provider-readiness.js +87 -0
  51. package/dist/provision.d.ts +46 -0
  52. package/dist/provision.js +197 -0
  53. package/dist/readiness.d.ts +4 -1
  54. package/dist/readiness.js +80 -8
  55. package/dist/registry/add.d.ts +22 -0
  56. package/dist/registry/add.js +198 -0
  57. package/dist/registry/bootstrap.d.ts +2 -0
  58. package/dist/registry/bootstrap.js +14 -0
  59. package/dist/registry/commands.d.ts +2 -0
  60. package/dist/registry/commands.js +99 -0
  61. package/dist/registry/context.d.ts +3 -0
  62. package/dist/registry/context.js +21 -0
  63. package/dist/registry/options.d.ts +2 -0
  64. package/dist/registry/options.js +65 -0
  65. package/dist/registry/receipt.d.ts +3 -0
  66. package/dist/registry/receipt.js +73 -0
  67. package/dist/registry/remote.d.ts +25 -0
  68. package/dist/registry/remote.js +168 -0
  69. package/dist/registry/resolve.d.ts +10 -0
  70. package/dist/registry/resolve.js +98 -0
  71. package/dist/registry/types.d.ts +64 -0
  72. package/dist/registry/usage.d.ts +1 -0
  73. package/dist/registry/usage.js +38 -0
  74. package/dist/render.js +3 -3
  75. package/dist/repository.d.ts +24 -0
  76. package/dist/repository.js +96 -0
  77. package/dist/scaffold/api.d.ts +2 -0
  78. package/dist/scaffold/api.js +13 -0
  79. package/dist/scaffold/auth.d.ts +3 -0
  80. package/dist/scaffold/auth.js +95 -0
  81. package/dist/scaffold/bootstrap.d.ts +2 -0
  82. package/dist/scaffold/bootstrap.js +34 -0
  83. package/dist/scaffold/compose.d.ts +4 -0
  84. package/dist/scaffold/compose.js +34 -0
  85. package/dist/scaffold/database.d.ts +2 -0
  86. package/dist/scaffold/database.js +43 -0
  87. package/dist/scaffold/documentation.d.ts +3 -0
  88. package/dist/scaffold/documentation.js +91 -0
  89. package/dist/scaffold/environment.d.ts +2 -0
  90. package/dist/scaffold/environment.js +5 -0
  91. package/dist/scaffold/files.d.ts +25 -0
  92. package/dist/scaffold/files.js +108 -0
  93. package/dist/scaffold/integrations.d.ts +3 -0
  94. package/dist/scaffold/integrations.js +7 -0
  95. package/dist/scaffold/services.d.ts +5 -0
  96. package/dist/scaffold/services.js +84 -0
  97. package/dist/scaffold/web.d.ts +2 -0
  98. package/dist/scaffold/web.js +102 -0
  99. package/dist/scaffold/workspace.d.ts +3 -0
  100. package/dist/scaffold/workspace.js +150 -0
  101. package/dist/security-backports.d.ts +3 -0
  102. package/dist/security-backports.js +26 -0
  103. package/dist/stack-registry.d.ts +80 -0
  104. package/dist/stack-registry.js +424 -0
  105. package/dist/standard.d.ts +6 -17
  106. package/dist/standard.js +41 -585
  107. package/dist/transaction.js +46 -26
  108. package/dist/util.js +12 -2
  109. package/dist/vercel.d.ts +98 -0
  110. package/dist/vercel.js +796 -0
  111. package/dist/version.d.ts +1 -1
  112. package/dist/version.js +1 -1
  113. package/dist/vinext.d.ts +1 -0
  114. package/dist/vinext.js +83 -0
  115. package/dist/workspace-graph.d.ts +7 -0
  116. package/dist/workspace-graph.js +73 -0
  117. package/docs/application-stack-standard.md +75 -674
  118. package/docs/delivery-workflow.md +83 -0
  119. package/docs/managed-hosting-architecture.md +87 -0
  120. package/docs/sponsorships.md +25 -0
  121. package/package.json +23 -28
  122. package/dist/project.d.ts +0 -4
  123. package/dist/standard-products.d.ts +0 -2
  124. package/dist/standard-products.js +0 -6
  125. /package/assets/{images/svg/logo-white-subtract.svg → anhedral-mark.svg} +0 -0
  126. /package/dist/{project.js → registry/types.js} +0 -0
package/dist/access.js ADDED
@@ -0,0 +1,93 @@
1
+ import path from 'node:path';
2
+ import { atomicJson, readConfig, targetDirectory, } from './project-state.js';
3
+ import { listCloudflare } from './cloudflare.js';
4
+ export function validatePrivateAudience(project, root) {
5
+ if (!project.access?.emails.length ||
6
+ project.access.emails.some((email) => !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)))
7
+ throw new Error('Private delivery requires explicit allowed email addresses.');
8
+ for (const target of project.targets) {
9
+ const config = readConfig(targetDirectory(root, target));
10
+ if (target.id === 'realtime' ||
11
+ config.durable_objects?.bindings?.some((item) => item.class_name === 'Rooms'))
12
+ throw new Error('Worker-level Access does not support WebSockets. Use a reviewed hostname Access workflow or application identity for realtime products.');
13
+ }
14
+ }
15
+ function policiesMatch(policies, emails) {
16
+ if (policies.length !== 1 || policies[0].decision !== 'allow')
17
+ return false;
18
+ const policy = policies[0];
19
+ if (!Array.isArray(policy.include) ||
20
+ !policy.include.length ||
21
+ policy.exclude?.length ||
22
+ policy.require?.length)
23
+ return false;
24
+ const actual = [];
25
+ for (const rule of policy.include) {
26
+ if (!rule || Object.keys(rule).length !== 1 || typeof rule.email?.email !== 'string')
27
+ return false;
28
+ actual.push(rule.email.email.toLowerCase());
29
+ }
30
+ return (JSON.stringify([...new Set(actual)].sort()) === JSON.stringify([...new Set(emails)].sort()));
31
+ }
32
+ /** Protect the entire Worker, including every route and preview, before product code is deployed. */
33
+ export async function reconcileAccess(root, project, request, create) {
34
+ validatePrivateAudience(project, root);
35
+ const receipts = [];
36
+ const workers = await listCloudflare(request, '/workers/workers');
37
+ const apps = await listCloudflare(request, '/access/apps');
38
+ for (const target of project.targets) {
39
+ const matches = workers.filter((item) => item.name === target.workerName);
40
+ if (matches.length > 1)
41
+ throw new Error('Ambiguous Worker identity.');
42
+ let worker = matches[0];
43
+ if (!worker && create)
44
+ worker = (await request('POST', '/workers/workers', { name: target.workerName }))
45
+ .result;
46
+ if (!worker || typeof worker.id !== 'string' || !/^[a-f0-9]{32}$/i.test(worker.id))
47
+ throw new Error('Provider did not return an immutable Worker ID.');
48
+ const destinations = [{ type: 'worker', worker_id: worker.id }];
49
+ const candidates = apps.filter((app) => Array.isArray(app.destinations) &&
50
+ app.destinations.some((destination) => destination.worker_id === worker.id));
51
+ if (candidates.length > 1)
52
+ throw new Error('Multiple Access applications target this Worker; reconcile policies explicitly.');
53
+ let app = candidates[0];
54
+ if (!app && create) {
55
+ app = (await request('POST', '/access/apps', {
56
+ name: `Anhedral ${project.id} ${target.id}`,
57
+ type: 'self_hosted',
58
+ session_duration: '24h',
59
+ destinations,
60
+ policies: [
61
+ {
62
+ name: 'Application members',
63
+ decision: 'allow',
64
+ include: project.access.emails.map((email) => ({ email: { email } })),
65
+ },
66
+ ],
67
+ })).result;
68
+ apps.push(app);
69
+ }
70
+ if (!app ||
71
+ typeof app.id !== 'string' ||
72
+ !/^[a-f0-9-]{36}$/i.test(app.id) ||
73
+ app.type !== 'self_hosted' ||
74
+ !Array.isArray(app.destinations) ||
75
+ app.destinations.length !== 1 ||
76
+ app.destinations[0].type !== 'worker' ||
77
+ app.destinations[0].worker_id !== worker.id)
78
+ throw new Error('Whole-Worker private Access protection is missing or differs from the requested policy.');
79
+ const policies = await listCloudflare(request, `/access/apps/${app.id}/policies`);
80
+ if (!policiesMatch(policies, project.access.emails))
81
+ throw new Error('Access policies differ from the explicit application members; no unrelated policy was overwritten.');
82
+ receipts.push({ target: target.id, workerId: worker.id, applicationId: app.id });
83
+ if (create)
84
+ atomicJson(path.join(root, '.anhedral/access.json'), {
85
+ schemaVersion: 1,
86
+ projectId: project.id,
87
+ accountId: project.accountId,
88
+ checkedAt: new Date().toISOString(),
89
+ receipts,
90
+ });
91
+ }
92
+ return receipts;
93
+ }
@@ -0,0 +1,346 @@
1
+ export declare const betterAuthSqliteSnapshot: {
2
+ version: string;
3
+ dialect: string;
4
+ id: string;
5
+ prevId: string;
6
+ tables: {
7
+ account: {
8
+ name: string;
9
+ columns: {
10
+ id: {
11
+ name: string;
12
+ type: string;
13
+ primaryKey: boolean;
14
+ notNull: boolean;
15
+ autoincrement: boolean;
16
+ };
17
+ account_id: {
18
+ name: string;
19
+ type: string;
20
+ primaryKey: boolean;
21
+ notNull: boolean;
22
+ autoincrement: boolean;
23
+ };
24
+ provider_id: {
25
+ name: string;
26
+ type: string;
27
+ primaryKey: boolean;
28
+ notNull: boolean;
29
+ autoincrement: boolean;
30
+ };
31
+ user_id: {
32
+ name: string;
33
+ type: string;
34
+ primaryKey: boolean;
35
+ notNull: boolean;
36
+ autoincrement: boolean;
37
+ };
38
+ access_token: {
39
+ name: string;
40
+ type: string;
41
+ primaryKey: boolean;
42
+ notNull: boolean;
43
+ autoincrement: boolean;
44
+ };
45
+ refresh_token: {
46
+ name: string;
47
+ type: string;
48
+ primaryKey: boolean;
49
+ notNull: boolean;
50
+ autoincrement: boolean;
51
+ };
52
+ id_token: {
53
+ name: string;
54
+ type: string;
55
+ primaryKey: boolean;
56
+ notNull: boolean;
57
+ autoincrement: boolean;
58
+ };
59
+ access_token_expires_at: {
60
+ name: string;
61
+ type: string;
62
+ primaryKey: boolean;
63
+ notNull: boolean;
64
+ autoincrement: boolean;
65
+ };
66
+ refresh_token_expires_at: {
67
+ name: string;
68
+ type: string;
69
+ primaryKey: boolean;
70
+ notNull: boolean;
71
+ autoincrement: boolean;
72
+ };
73
+ scope: {
74
+ name: string;
75
+ type: string;
76
+ primaryKey: boolean;
77
+ notNull: boolean;
78
+ autoincrement: boolean;
79
+ };
80
+ password: {
81
+ name: string;
82
+ type: string;
83
+ primaryKey: boolean;
84
+ notNull: boolean;
85
+ autoincrement: boolean;
86
+ };
87
+ created_at: {
88
+ name: string;
89
+ type: string;
90
+ primaryKey: boolean;
91
+ notNull: boolean;
92
+ autoincrement: boolean;
93
+ };
94
+ updated_at: {
95
+ name: string;
96
+ type: string;
97
+ primaryKey: boolean;
98
+ notNull: boolean;
99
+ autoincrement: boolean;
100
+ };
101
+ };
102
+ indexes: {
103
+ account_user_id_idx: {
104
+ name: string;
105
+ columns: string[];
106
+ isUnique: boolean;
107
+ };
108
+ };
109
+ foreignKeys: {
110
+ account_user_id_user_id_fk: {
111
+ name: string;
112
+ tableFrom: string;
113
+ tableTo: string;
114
+ columnsFrom: string[];
115
+ columnsTo: string[];
116
+ onDelete: string;
117
+ onUpdate: string;
118
+ };
119
+ };
120
+ compositePrimaryKeys: {};
121
+ uniqueConstraints: {};
122
+ checkConstraints: {};
123
+ };
124
+ session: {
125
+ name: string;
126
+ columns: {
127
+ id: {
128
+ name: string;
129
+ type: string;
130
+ primaryKey: boolean;
131
+ notNull: boolean;
132
+ autoincrement: boolean;
133
+ };
134
+ expires_at: {
135
+ name: string;
136
+ type: string;
137
+ primaryKey: boolean;
138
+ notNull: boolean;
139
+ autoincrement: boolean;
140
+ };
141
+ token: {
142
+ name: string;
143
+ type: string;
144
+ primaryKey: boolean;
145
+ notNull: boolean;
146
+ autoincrement: boolean;
147
+ };
148
+ created_at: {
149
+ name: string;
150
+ type: string;
151
+ primaryKey: boolean;
152
+ notNull: boolean;
153
+ autoincrement: boolean;
154
+ };
155
+ updated_at: {
156
+ name: string;
157
+ type: string;
158
+ primaryKey: boolean;
159
+ notNull: boolean;
160
+ autoincrement: boolean;
161
+ };
162
+ ip_address: {
163
+ name: string;
164
+ type: string;
165
+ primaryKey: boolean;
166
+ notNull: boolean;
167
+ autoincrement: boolean;
168
+ };
169
+ user_agent: {
170
+ name: string;
171
+ type: string;
172
+ primaryKey: boolean;
173
+ notNull: boolean;
174
+ autoincrement: boolean;
175
+ };
176
+ user_id: {
177
+ name: string;
178
+ type: string;
179
+ primaryKey: boolean;
180
+ notNull: boolean;
181
+ autoincrement: boolean;
182
+ };
183
+ };
184
+ indexes: {
185
+ session_token_unique: {
186
+ name: string;
187
+ columns: string[];
188
+ isUnique: boolean;
189
+ };
190
+ session_user_id_idx: {
191
+ name: string;
192
+ columns: string[];
193
+ isUnique: boolean;
194
+ };
195
+ };
196
+ foreignKeys: {
197
+ session_user_id_user_id_fk: {
198
+ name: string;
199
+ tableFrom: string;
200
+ tableTo: string;
201
+ columnsFrom: string[];
202
+ columnsTo: string[];
203
+ onDelete: string;
204
+ onUpdate: string;
205
+ };
206
+ };
207
+ compositePrimaryKeys: {};
208
+ uniqueConstraints: {};
209
+ checkConstraints: {};
210
+ };
211
+ user: {
212
+ name: string;
213
+ columns: {
214
+ id: {
215
+ name: string;
216
+ type: string;
217
+ primaryKey: boolean;
218
+ notNull: boolean;
219
+ autoincrement: boolean;
220
+ };
221
+ name: {
222
+ name: string;
223
+ type: string;
224
+ primaryKey: boolean;
225
+ notNull: boolean;
226
+ autoincrement: boolean;
227
+ };
228
+ email: {
229
+ name: string;
230
+ type: string;
231
+ primaryKey: boolean;
232
+ notNull: boolean;
233
+ autoincrement: boolean;
234
+ };
235
+ email_verified: {
236
+ name: string;
237
+ type: string;
238
+ primaryKey: boolean;
239
+ notNull: boolean;
240
+ autoincrement: boolean;
241
+ default: boolean;
242
+ };
243
+ image: {
244
+ name: string;
245
+ type: string;
246
+ primaryKey: boolean;
247
+ notNull: boolean;
248
+ autoincrement: boolean;
249
+ };
250
+ created_at: {
251
+ name: string;
252
+ type: string;
253
+ primaryKey: boolean;
254
+ notNull: boolean;
255
+ autoincrement: boolean;
256
+ };
257
+ updated_at: {
258
+ name: string;
259
+ type: string;
260
+ primaryKey: boolean;
261
+ notNull: boolean;
262
+ autoincrement: boolean;
263
+ };
264
+ };
265
+ indexes: {
266
+ user_email_unique: {
267
+ name: string;
268
+ columns: string[];
269
+ isUnique: boolean;
270
+ };
271
+ };
272
+ foreignKeys: {};
273
+ compositePrimaryKeys: {};
274
+ uniqueConstraints: {};
275
+ checkConstraints: {};
276
+ };
277
+ verification: {
278
+ name: string;
279
+ columns: {
280
+ id: {
281
+ name: string;
282
+ type: string;
283
+ primaryKey: boolean;
284
+ notNull: boolean;
285
+ autoincrement: boolean;
286
+ };
287
+ identifier: {
288
+ name: string;
289
+ type: string;
290
+ primaryKey: boolean;
291
+ notNull: boolean;
292
+ autoincrement: boolean;
293
+ };
294
+ value: {
295
+ name: string;
296
+ type: string;
297
+ primaryKey: boolean;
298
+ notNull: boolean;
299
+ autoincrement: boolean;
300
+ };
301
+ expires_at: {
302
+ name: string;
303
+ type: string;
304
+ primaryKey: boolean;
305
+ notNull: boolean;
306
+ autoincrement: boolean;
307
+ };
308
+ created_at: {
309
+ name: string;
310
+ type: string;
311
+ primaryKey: boolean;
312
+ notNull: boolean;
313
+ autoincrement: boolean;
314
+ };
315
+ updated_at: {
316
+ name: string;
317
+ type: string;
318
+ primaryKey: boolean;
319
+ notNull: boolean;
320
+ autoincrement: boolean;
321
+ };
322
+ };
323
+ indexes: {
324
+ verification_identifier_idx: {
325
+ name: string;
326
+ columns: string[];
327
+ isUnique: boolean;
328
+ };
329
+ };
330
+ foreignKeys: {};
331
+ compositePrimaryKeys: {};
332
+ uniqueConstraints: {};
333
+ checkConstraints: {};
334
+ };
335
+ };
336
+ views: {};
337
+ enums: {};
338
+ _meta: {
339
+ schemas: {};
340
+ tables: {};
341
+ columns: {};
342
+ };
343
+ internal: {
344
+ indexes: {};
345
+ };
346
+ };