@feltdb/core 0.8.0 → 0.8.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.
Files changed (74) hide show
  1. package/dist/application-development.d.ts +7 -2
  2. package/dist/application-development.d.ts.map +1 -1
  3. package/dist/application-development.js +7 -13
  4. package/dist/application-manifest.d.ts +1 -0
  5. package/dist/application-manifest.d.ts.map +1 -1
  6. package/dist/application-manifest.js +1 -1
  7. package/dist/application-understanding.d.ts +76 -0
  8. package/dist/application-understanding.d.ts.map +1 -0
  9. package/dist/application-understanding.js +282 -0
  10. package/dist/cli/ai-model-config.js +3 -3
  11. package/dist/cli/commands.js +131 -38
  12. package/dist/cli/proposal-client.js +5 -1
  13. package/dist/cli/publish-engine.js +1 -1
  14. package/dist/cli/repository-evidence.js +55 -0
  15. package/dist/cli/source-sync.js +190 -75
  16. package/dist/convergence.d.ts +55 -0
  17. package/dist/convergence.d.ts.map +1 -0
  18. package/dist/convergence.js +63 -0
  19. package/dist/create/managed-account.js +1 -0
  20. package/dist/create/package-versions.js +1 -1
  21. package/dist/create/server-source/crates/feltdb/src/application.rs +4 -0
  22. package/dist/create/server-source/crates/feltdb-server/src/connections.rs +14 -0
  23. package/dist/create/server-source/crates/feltdb-server/src/main.rs +174 -24
  24. package/dist/create/server-source/crates/feltdb-server/src/tenancy.rs +8 -1
  25. package/dist/create/template/default-project/src/context/AuthContext.tsx +9 -1
  26. package/dist/create/template/default-project/src/pages/SignUp.tsx +1 -1
  27. package/dist/flowspec.d.ts.map +1 -1
  28. package/dist/flowspec.js +6 -1
  29. package/dist/http-client.d.ts +32 -1
  30. package/dist/http-client.d.ts.map +1 -1
  31. package/dist/http-client.js +14 -2
  32. package/dist/http-db.d.ts +3 -0
  33. package/dist/http-db.d.ts.map +1 -1
  34. package/dist/http-db.js +28 -3
  35. package/dist/index-core.d.ts +3 -0
  36. package/dist/index-core.d.ts.map +1 -1
  37. package/dist/index-core.js +3 -0
  38. package/dist/intent.d.ts +98 -0
  39. package/dist/intent.d.ts.map +1 -0
  40. package/dist/intent.js +343 -0
  41. package/dist/module-intent.d.ts +19 -5
  42. package/dist/module-intent.d.ts.map +1 -1
  43. package/dist/module-intent.js +211 -62
  44. package/dist/module.d.ts +41 -12
  45. package/dist/module.d.ts.map +1 -1
  46. package/dist/module.js +543 -38
  47. package/dist/proposal.d.ts +13 -1
  48. package/dist/proposal.d.ts.map +1 -1
  49. package/dist/proposal.js +21 -4
  50. package/dist/studio/components/AskFeltDB.d.ts.map +1 -1
  51. package/dist/studio/components/ProposalBrowser.d.ts +1 -1
  52. package/dist/studio/components/ProposalBrowser.d.ts.map +1 -1
  53. package/dist/studio/components/index.js +1 -1
  54. package/dist/studio/{components-CNSNrmA9.js → components-Duq2xQWt.js} +251 -193
  55. package/dist/studio/index.js +1 -1
  56. package/dist/studio/studio.css +1 -1
  57. package/dist/studio/utils/proposal-api.d.ts +4 -1
  58. package/dist/studio/utils/proposal-api.d.ts.map +1 -1
  59. package/dist/studio/utils/proposal-api.js +3 -0
  60. package/dist/studio-app/assets/{feltdb_wasm-CSB6KVgw.js → feltdb_wasm-bIqcRzAr.js} +1 -1
  61. package/dist/studio-app/assets/feltdb_wasm_bg-BE79okwX.wasm +0 -0
  62. package/dist/studio-app/assets/{index-yazaWMUN.css → index-Cd_NPw14.css} +1 -1
  63. package/dist/studio-app/assets/index-XGYdlElN.js +29 -0
  64. package/dist/studio-app/index.html +2 -2
  65. package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
  66. package/dist/workspace/local-development-authority.d.ts +2 -0
  67. package/dist/workspace/local-development-authority.d.ts.map +1 -1
  68. package/dist/workspace/local-development-authority.js +65 -2
  69. package/package.json +1 -1
  70. package/dist/studio-app/assets/dist-CCOk39Uc.js +0 -1
  71. package/dist/studio-app/assets/feltdb_wasm_bg-Dd1fnO9U.wasm +0 -0
  72. package/dist/studio-app/assets/index-Bncji3aN.js +0 -43
  73. package/dist/studio-app/assets/lib-B2_7fcn7.js +0 -69
  74. package/dist/studio-app/assets/worker-CARZ5g7K.js +0 -69
package/dist/module.js CHANGED
@@ -1,46 +1,535 @@
1
+ const model = (name, ownership = "external-authoritative") => ({
2
+ name,
3
+ authority: "external",
4
+ ownership,
5
+ fields: [
6
+ {
7
+ name: "id",
8
+ type: "text",
9
+ immutable: true,
10
+ externally_owned: true,
11
+ application_readable: true,
12
+ },
13
+ {
14
+ name: "status",
15
+ type: "text",
16
+ optional: true,
17
+ externally_owned: true,
18
+ application_readable: true,
19
+ },
20
+ {
21
+ name: "created_at",
22
+ type: "datetime",
23
+ externally_owned: true,
24
+ application_readable: true,
25
+ },
26
+ {
27
+ name: "metadata",
28
+ type: "json",
29
+ optional: true,
30
+ externally_owned: true,
31
+ application_readable: true,
32
+ },
33
+ ],
34
+ });
1
35
  const stripe = {
2
- id: 'stripe', name: 'Stripe-compatible billing', version: '1.0.0', provider: 'stripe-compatible',
3
- compatibility: ['stripe', 'stripe-compatible'],
4
- models: ['Customer', 'Product', 'Price', 'Subscription', 'SubscriptionItem', 'Invoice', 'PaymentIntent', 'CheckoutSession', 'PaymentMethod', 'Refund', 'WebhookEvent']
5
- .map(name => ({ name, authority: 'external', ownership: 'external-authoritative', fields: [
6
- { name: 'id', type: 'text', immutable: true, externally_owned: true, application_readable: true },
7
- { name: 'status', type: 'text', optional: true, externally_owned: true, application_readable: true },
8
- { name: 'created_at', type: 'datetime', externally_owned: true, application_readable: true },
9
- { name: 'metadata', type: 'json', optional: true, externally_owned: true, application_readable: true },
10
- ] })),
36
+ id: "stripe",
37
+ name: "Stripe-compatible billing",
38
+ version: "1.0.0",
39
+ provider: "stripe-compatible",
40
+ compatibility: ["stripe", "stripe-compatible"],
41
+ intent_keywords: ["stripe", "billing", "plan", "subscription"],
42
+ models: [
43
+ "Customer",
44
+ "Product",
45
+ "Price",
46
+ "Subscription",
47
+ "SubscriptionItem",
48
+ "Invoice",
49
+ "PaymentIntent",
50
+ "CheckoutSession",
51
+ "PaymentMethod",
52
+ "Refund",
53
+ "WebhookEvent",
54
+ ].map((name) => model(name)),
11
55
  relationships: [
12
- { from: 'Customer', to: 'Subscription', kind: 'many' }, { from: 'Subscription', to: 'SubscriptionItem', kind: 'many' },
13
- { from: 'SubscriptionItem', to: 'Price', kind: 'one' }, { from: 'Price', to: 'Product', kind: 'one' },
14
- { from: 'Customer', to: 'Invoice', kind: 'many' }, { from: 'Invoice', to: 'PaymentIntent', kind: 'one' },
15
- ],
16
- events: ['stripe.customer.created', 'stripe.customer.updated', 'stripe.subscription.created', 'stripe.subscription.updated', 'stripe.subscription.deleted', 'stripe.invoice.paid', 'stripe.invoice.payment_failed', 'stripe.checkout.session.completed'],
17
- capabilities: ['stripe.customer.read', 'stripe.customer.create', 'stripe.checkout.create', 'stripe.subscription.read', 'stripe.subscription.create', 'stripe.subscription.cancel', 'stripe.invoice.read', 'stripe.webhooks.receive'],
18
- workflows: ['ReconcileSubscription', 'ReconcileFailedPayment'],
19
- configuration: [{ name: 'STRIPE_PUBLISHABLE_KEY', required: false, description: 'Browser-safe publishable provider key' }],
20
- secrets: [{ name: 'STRIPE_SECRET_KEY', required: true, description: 'Server-side provider credential' }, { name: 'STRIPE_WEBHOOK_SECRET', required: true, environments: ['production'], description: 'Webhook signature verification secret' }],
21
- validation: ['Webhook receivers must verify signatures', 'Checkout creation requires authenticated authorization'],
22
- dependencies: [],
56
+ { from: "Customer", to: "Subscription", kind: "many" },
57
+ { from: "Subscription", to: "SubscriptionItem", kind: "many" },
58
+ { from: "SubscriptionItem", to: "Price", kind: "one" },
59
+ { from: "Price", to: "Product", kind: "one" },
60
+ { from: "Customer", to: "Invoice", kind: "many" },
61
+ { from: "Invoice", to: "PaymentIntent", kind: "one" },
62
+ ],
63
+ events: [
64
+ "stripe.customer.created",
65
+ "stripe.customer.updated",
66
+ "stripe.subscription.created",
67
+ "stripe.subscription.updated",
68
+ "stripe.subscription.deleted",
69
+ "stripe.invoice.paid",
70
+ "stripe.invoice.payment_failed",
71
+ "stripe.checkout.session.completed",
72
+ ],
73
+ capabilities: [
74
+ "stripe.customer.read",
75
+ "stripe.customer.create",
76
+ "stripe.checkout.create",
77
+ "stripe.subscription.read",
78
+ "stripe.subscription.create",
79
+ "stripe.subscription.cancel",
80
+ "stripe.invoice.read",
81
+ "stripe.webhooks.receive",
82
+ ],
83
+ workflows: ["ReconcileSubscription", "ReconcileFailedPayment"],
84
+ configuration: [
85
+ {
86
+ name: "STRIPE_PUBLISHABLE_KEY",
87
+ required: false,
88
+ description: "Browser-safe publishable provider key",
89
+ visibility: "browser",
90
+ },
91
+ ],
92
+ secrets: [
93
+ {
94
+ name: "STRIPE_SECRET_KEY",
95
+ required: true,
96
+ description: "Server-side provider credential",
97
+ visibility: "server",
98
+ },
99
+ {
100
+ name: "STRIPE_WEBHOOK_SECRET",
101
+ required: true,
102
+ environments: ["production"],
103
+ description: "Webhook signature verification secret",
104
+ visibility: "server",
105
+ },
106
+ ],
107
+ validation: [
108
+ "Webhook receivers must verify signatures",
109
+ "Checkout creation requires authenticated authorization",
110
+ ],
111
+ dependencies: [
112
+ {
113
+ name: "authentication",
114
+ description: "Checkout requires an authenticated application identity",
115
+ any_collections: ["User", "Account"],
116
+ any_capabilities: ["auth.session.read", "authentication"],
117
+ },
118
+ ],
23
119
  authorization: [
24
- { capability: 'stripe.checkout.create', subject: 'authenticated', implication: 'A signed-in billing owner may create a hosted checkout session' },
25
- { capability: 'stripe.subscription.cancel', subject: 'owner', implication: 'Only the billing owner may cancel a subscription' },
120
+ {
121
+ capability: "stripe.checkout.create",
122
+ subject: "authenticated",
123
+ implication: "A signed-in billing owner may create a hosted checkout session",
124
+ },
125
+ {
126
+ capability: "stripe.subscription.cancel",
127
+ subject: "owner",
128
+ implication: "Only the billing owner may cancel a subscription",
129
+ },
130
+ ],
131
+ extension_application_models: [
132
+ {
133
+ name: "BillingPlan",
134
+ ownership: "application-authoritative",
135
+ purpose: "Application pricing and entitlement plan",
136
+ fields: [
137
+ { name: "code", type: "text" },
138
+ { name: "interval", type: "enum(monthly,annual)" },
139
+ { name: "price", type: "ref $module.Price" },
140
+ { name: "active", type: "boolean" },
141
+ ],
142
+ },
26
143
  ],
27
144
  patterns: [
28
- { name: 'organization billing', when: 'The application contains Organization or Workspace state', owner_candidates: ['Organization', 'Workspace'], application_models: [
29
- { name: 'BillingAccount', ownership: 'application-authoritative', purpose: 'Connect the application billing owner to provider state' },
30
- { name: 'Entitlement', ownership: 'derived', purpose: 'Materialize product access from reconciled subscription state' },
31
- ] },
32
- { name: 'user billing', when: 'The application is user-centric and has no organizational owner', owner_candidates: ['User', 'Account'], application_models: [
33
- { name: 'BillingAccount', ownership: 'application-authoritative', purpose: 'Connect the user to provider state' },
34
- { name: 'Entitlement', ownership: 'derived', purpose: 'Materialize product access from reconciled subscription state' },
35
- ] },
145
+ {
146
+ name: "organization billing",
147
+ when: "The application contains an organizational owner",
148
+ owner_candidates: ["Organization", "Workspace"],
149
+ application_models: [
150
+ {
151
+ name: "BillingAccount",
152
+ ownership: "application-authoritative",
153
+ purpose: "Connect the application billing owner to provider state",
154
+ fields: [
155
+ { name: "owner", type: "ref $owner" },
156
+ { name: "customer", type: "ref $module.Customer" },
157
+ {
158
+ name: "subscription",
159
+ type: "ref $module.Subscription",
160
+ optional: true,
161
+ },
162
+ { name: "status", type: "text" },
163
+ ],
164
+ },
165
+ {
166
+ name: "Entitlement",
167
+ ownership: "derived",
168
+ purpose: "Materialize product access from reconciled subscription state",
169
+ fields: [
170
+ { name: "billing_account", type: "ref BillingAccount" },
171
+ { name: "key", type: "text" },
172
+ { name: "active", type: "boolean" },
173
+ ],
174
+ },
175
+ ],
176
+ },
177
+ {
178
+ name: "user billing",
179
+ when: "The application is user-centric",
180
+ owner_candidates: ["User", "Account"],
181
+ application_models: [
182
+ {
183
+ name: "BillingAccount",
184
+ ownership: "application-authoritative",
185
+ purpose: "Connect the user to provider state",
186
+ fields: [
187
+ { name: "owner", type: "ref $owner" },
188
+ { name: "customer", type: "ref $module.Customer" },
189
+ {
190
+ name: "subscription",
191
+ type: "ref $module.Subscription",
192
+ optional: true,
193
+ },
194
+ { name: "status", type: "text" },
195
+ ],
196
+ },
197
+ {
198
+ name: "Entitlement",
199
+ ownership: "derived",
200
+ purpose: "Materialize product access from reconciled subscription state",
201
+ fields: [
202
+ { name: "billing_account", type: "ref BillingAccount" },
203
+ { name: "key", type: "text" },
204
+ { name: "active", type: "boolean" },
205
+ ],
206
+ },
207
+ ],
208
+ },
36
209
  ],
37
210
  reconciliation: [
38
- { event: 'stripe.subscription.updated', workflow: 'ReconcileSubscription', reads: ['stripe.Subscription', 'BillingAccount'], writes: ['BillingAccount', 'Entitlement'], outcome: 'Subscription changes become application entitlements' },
39
- { event: 'stripe.invoice.payment_failed', workflow: 'ReconcileFailedPayment', reads: ['stripe.Invoice', 'BillingAccount'], writes: ['BillingAccount', 'Entitlement'], outcome: 'Failed payment state restricts derived entitlements' },
211
+ {
212
+ event: "stripe.subscription.updated",
213
+ workflow: "ReconcileSubscription",
214
+ reads: ["stripe.Subscription", "BillingAccount"],
215
+ writes: ["BillingAccount", "Entitlement"],
216
+ outcome: "Subscription changes become application entitlements",
217
+ },
218
+ {
219
+ event: "stripe.invoice.payment_failed",
220
+ workflow: "ReconcileFailedPayment",
221
+ reads: ["stripe.Invoice", "BillingAccount"],
222
+ writes: ["BillingAccount", "Entitlement"],
223
+ outcome: "Failed payment state restricts derived entitlements",
224
+ },
225
+ ],
226
+ placement: {
227
+ owner_claim: "billing.owner",
228
+ primary_application_model: "BillingAccount",
229
+ owner_field: "owner",
230
+ },
231
+ source_artifacts: [
232
+ {
233
+ path: "src/integrations/stripe/domain.ts",
234
+ role: "module-domain",
235
+ purpose: "Application billing state",
236
+ },
237
+ {
238
+ path: "src/integrations/stripe/provider-boundary.ts",
239
+ role: "module-provider-boundary",
240
+ purpose: "Stripe operations and verified event boundary",
241
+ },
242
+ {
243
+ path: "src/integrations/stripe/reconcile.ts",
244
+ role: "module-reconciliation",
245
+ purpose: "Subscription to entitlement reconciliation",
246
+ },
247
+ {
248
+ path: "src/integrations/stripe/IntegrationView.tsx",
249
+ role: "module-ui",
250
+ purpose: "Billing application experience",
251
+ },
252
+ {
253
+ path: "src/integrations/stripe/module.test.ts",
254
+ role: "module-contract-test",
255
+ purpose: "Module contract test",
256
+ },
40
257
  ],
41
258
  };
42
- const definitions = new Map([[stripe.id, stripe]]);
43
- export function listFeltDBModules() { return [...definitions.values()].map(value => structuredClone(value)); }
259
+ const github = {
260
+ id: "github",
261
+ name: "GitHub App collaboration",
262
+ version: "1.0.0",
263
+ provider: "github-app",
264
+ compatibility: ["github", "github-app"],
265
+ intent_keywords: ["github", "repository", "repositories", "issues"],
266
+ models: [
267
+ model("Organization"),
268
+ model("Repository"),
269
+ model("Installation", "synchronized"),
270
+ model("Issue"),
271
+ model("Membership"),
272
+ ],
273
+ relationships: [
274
+ { from: "Organization", to: "Repository", kind: "many" },
275
+ { from: "Installation", to: "Repository", kind: "many" },
276
+ { from: "Repository", to: "Issue", kind: "many" },
277
+ ],
278
+ events: [
279
+ "github.repository.created",
280
+ "github.repository.updated",
281
+ "github.repository.deleted",
282
+ "github.installation.created",
283
+ "github.installation.deleted",
284
+ "github.membership.added",
285
+ "github.membership.removed",
286
+ ],
287
+ capabilities: [
288
+ "github.repository.read",
289
+ "github.repository.create",
290
+ "github.issue.read",
291
+ "github.issue.write",
292
+ "github.webhooks.receive",
293
+ ],
294
+ workflows: ["SynchronizeRepository", "SynchronizeInstallation"],
295
+ configuration: [
296
+ {
297
+ name: "GITHUB_APP_ID",
298
+ required: true,
299
+ description: "GitHub App identifier",
300
+ visibility: "server",
301
+ },
302
+ ],
303
+ secrets: [
304
+ {
305
+ name: "GITHUB_PRIVATE_KEY",
306
+ required: true,
307
+ description: "GitHub App signing key",
308
+ visibility: "server",
309
+ },
310
+ {
311
+ name: "GITHUB_WEBHOOK_SECRET",
312
+ required: true,
313
+ description: "GitHub webhook verification secret",
314
+ visibility: "server",
315
+ },
316
+ ],
317
+ validation: [
318
+ "Webhook receivers must verify signatures",
319
+ "Repository writes require explicit application authorization",
320
+ ],
321
+ dependencies: [
322
+ {
323
+ name: "authentication",
324
+ description: "GitHub installation management requires authenticated identity",
325
+ any_collections: ["User", "Account"],
326
+ any_capabilities: ["auth.session.read", "authentication"],
327
+ },
328
+ ],
329
+ authorization: [
330
+ {
331
+ capability: "github.repository.read",
332
+ subject: "authenticated",
333
+ implication: "Authenticated members may read connected repositories",
334
+ },
335
+ {
336
+ capability: "github.repository.create",
337
+ subject: "owner",
338
+ implication: "The integration owner controls repository creation",
339
+ },
340
+ ],
341
+ patterns: [
342
+ {
343
+ name: "organizational collaboration",
344
+ when: "Projects belong to an organization or workspace",
345
+ owner_candidates: ["Organization", "Workspace"],
346
+ application_models: [
347
+ {
348
+ name: "GitHubConnection",
349
+ ownership: "application-authoritative",
350
+ purpose: "Bind an application owner to a GitHub App installation",
351
+ fields: [
352
+ { name: "owner", type: "ref $owner" },
353
+ { name: "installation", type: "ref $module.Installation" },
354
+ { name: "status", type: "text" },
355
+ ],
356
+ },
357
+ {
358
+ name: "RepositoryConnection",
359
+ ownership: "synchronized",
360
+ purpose: "Map provider repositories into application projects",
361
+ fields: [
362
+ { name: "connection", type: "ref GitHubConnection" },
363
+ { name: "repository", type: "ref $module.Repository" },
364
+ { name: "project", type: "ref $project", optional: true },
365
+ { name: "synchronized_at", type: "datetime" },
366
+ ],
367
+ },
368
+ ],
369
+ },
370
+ {
371
+ name: "personal collaboration",
372
+ when: "Projects belong directly to a user",
373
+ owner_candidates: ["User", "Account"],
374
+ application_models: [
375
+ {
376
+ name: "GitHubConnection",
377
+ ownership: "application-authoritative",
378
+ purpose: "Bind a user to a GitHub App installation",
379
+ fields: [
380
+ { name: "owner", type: "ref $owner" },
381
+ { name: "installation", type: "ref $module.Installation" },
382
+ { name: "status", type: "text" },
383
+ ],
384
+ },
385
+ {
386
+ name: "RepositoryConnection",
387
+ ownership: "synchronized",
388
+ purpose: "Map provider repositories into application projects",
389
+ fields: [
390
+ { name: "connection", type: "ref GitHubConnection" },
391
+ { name: "repository", type: "ref $module.Repository" },
392
+ { name: "project", type: "ref $project", optional: true },
393
+ { name: "synchronized_at", type: "datetime" },
394
+ ],
395
+ },
396
+ ],
397
+ },
398
+ ],
399
+ reconciliation: [
400
+ {
401
+ event: "github.repository.updated",
402
+ workflow: "SynchronizeRepository",
403
+ reads: ["github.Repository", "RepositoryConnection"],
404
+ writes: ["RepositoryConnection"],
405
+ outcome: "Repository changes synchronize into application project state",
406
+ },
407
+ {
408
+ event: "github.installation.created",
409
+ workflow: "SynchronizeInstallation",
410
+ reads: ["github.Installation"],
411
+ writes: ["GitHubConnection"],
412
+ outcome: "GitHub App installations become application connections",
413
+ },
414
+ ],
415
+ placement: {
416
+ owner_claim: "repository.owner",
417
+ primary_application_model: "GitHubConnection",
418
+ owner_field: "owner",
419
+ },
420
+ source_artifacts: [
421
+ {
422
+ path: "src/integrations/github/domain.ts",
423
+ role: "module-domain",
424
+ purpose: "GitHub connection state",
425
+ },
426
+ {
427
+ path: "src/integrations/github/provider-boundary.ts",
428
+ role: "module-provider-boundary",
429
+ purpose: "GitHub App operations and webhook verification",
430
+ },
431
+ {
432
+ path: "src/integrations/github/reconcile.ts",
433
+ role: "module-reconciliation",
434
+ purpose: "Repository synchronization",
435
+ },
436
+ {
437
+ path: "src/integrations/github/IntegrationView.tsx",
438
+ role: "module-ui",
439
+ purpose: "Repository connection experience",
440
+ },
441
+ {
442
+ path: "src/integrations/github/module.test.ts",
443
+ role: "module-contract-test",
444
+ purpose: "Module contract test",
445
+ },
446
+ ],
447
+ };
448
+ const definitions = new Map();
449
+ export function validateFeltDBModule(module) {
450
+ const errors = [];
451
+ for (const key of ["id", "name", "version", "provider"])
452
+ if (!module[key])
453
+ errors.push(`missing:${key}`);
454
+ for (const name of [
455
+ "compatibility",
456
+ "models",
457
+ "relationships",
458
+ "events",
459
+ "workflows",
460
+ "capabilities",
461
+ "configuration",
462
+ "secrets",
463
+ "authorization",
464
+ "dependencies",
465
+ "patterns",
466
+ "reconciliation",
467
+ "source_artifacts",
468
+ ])
469
+ if (!Array.isArray(module[name]))
470
+ errors.push(`missing:${name}`);
471
+ for (const item of module.models ?? [])
472
+ if (![
473
+ "external-authoritative",
474
+ "application-authoritative",
475
+ "derived",
476
+ "synchronized",
477
+ ].includes(item.ownership))
478
+ errors.push(`invalid_ownership:${item.name}`);
479
+ if (!module.placement?.owner_claim ||
480
+ !module.placement?.primary_application_model ||
481
+ !module.placement?.owner_field)
482
+ errors.push("missing:placement");
483
+ for (const pattern of module.patterns ?? [])
484
+ for (const applicationModel of pattern.application_models)
485
+ if (!applicationModel.fields?.length)
486
+ errors.push(`missing_fields:${applicationModel.name}`);
487
+ const modelNames = new Set((module.models ?? []).map(value => value.name));
488
+ for (const relationship of module.relationships ?? []) {
489
+ if (!modelNames.has(relationship.from))
490
+ errors.push(`unknown_relationship_model:${relationship.from}`);
491
+ if (!modelNames.has(relationship.to))
492
+ errors.push(`unknown_relationship_model:${relationship.to}`);
493
+ }
494
+ const events = new Set(module.events ?? []);
495
+ const workflows = new Set(module.workflows ?? []);
496
+ const capabilities = new Set(module.capabilities ?? []);
497
+ for (const reconciliation of module.reconciliation ?? []) {
498
+ if (!events.has(reconciliation.event))
499
+ errors.push(`undeclared_reconciliation_event:${reconciliation.event}`);
500
+ if (!workflows.has(reconciliation.workflow))
501
+ errors.push(`undeclared_reconciliation_workflow:${reconciliation.workflow}`);
502
+ }
503
+ for (const authorization of module.authorization ?? [])
504
+ if (!capabilities.has(authorization.capability))
505
+ errors.push(`undeclared_authorization_capability:${authorization.capability}`);
506
+ for (const secret of module.secrets ?? [])
507
+ if (secret.visibility === 'browser' || secret.name.startsWith('VITE_'))
508
+ errors.push(`browser_secret:${secret.name}`);
509
+ const sourceRoles = new Set(['module-domain', 'module-provider-boundary', 'module-reconciliation', 'module-ui', 'module-contract-test']);
510
+ for (const artifact of module.source_artifacts ?? [])
511
+ if (!artifact.path.startsWith(`src/integrations/${module.id}/`) || !sourceRoles.has(artifact.role))
512
+ errors.push(`invalid_source_artifact:${artifact.path}`);
513
+ return [...new Set(errors)];
514
+ }
515
+ export function registerFeltDBModule(module) {
516
+ const errors = validateFeltDBModule(module);
517
+ if (errors.length)
518
+ throw new Error(`MODULE_CONFORMANCE_FAILED: ${errors.join(", ")}`);
519
+ if (definitions.has(module.id))
520
+ throw new Error(`MODULE_ALREADY_REGISTERED: ${module.id}`);
521
+ definitions.set(module.id, structuredClone(module));
522
+ return () => {
523
+ definitions.delete(module.id);
524
+ };
525
+ }
526
+ registerFeltDBModule(stripe);
527
+ registerFeltDBModule(github);
528
+ export function listFeltDBModules() {
529
+ return [...definitions.values()]
530
+ .map((value) => structuredClone(value))
531
+ .sort((a, b) => a.id.localeCompare(b.id));
532
+ }
44
533
  export function resolveFeltDBModule(declaration) {
45
534
  const definition = definitions.get(declaration.name);
46
535
  if (!definition)
@@ -53,9 +542,25 @@ export function resolveFeltDBModule(declaration) {
53
542
  }
54
543
  export function findFeltDBModules(query) {
55
544
  const normalized = query.trim().toLowerCase();
56
- return listFeltDBModules().filter(module => module.id === normalized || module.name.toLowerCase().includes(normalized) || module.compatibility.some(value => value.includes(normalized)));
545
+ return listFeltDBModules().filter((module) => module.id === normalized ||
546
+ module.name.toLowerCase().includes(normalized) ||
547
+ module.compatibility.some((value) => value.includes(normalized)) ||
548
+ module.intent_keywords.includes(normalized));
549
+ }
550
+ export function resolveFeltDBModules(declarations = []) {
551
+ return declarations
552
+ .map(resolveFeltDBModule)
553
+ .sort((a, b) => a.id.localeCompare(b.id));
57
554
  }
58
- export function resolveFeltDBModules(declarations = []) { return declarations.map(resolveFeltDBModule).sort((a, b) => a.id.localeCompare(b.id)); }
59
- export function validateResolvedModules(modules, environment = 'development') {
60
- return modules.flatMap(module => [...module.secrets.filter(value => value.required && (!value.environments || value.environments.includes(environment))).map(value => `${value.name} is required in ${environment} runtime configuration`), ...module.capabilities.filter(value => value.endsWith('.create')).map(value => `${value} requires an explicit authorization policy`)]);
555
+ export function validateResolvedModules(modules, environment = "development") {
556
+ return modules.flatMap((module) => [
557
+ ...validateFeltDBModule(module).map((value) => `${module.id}: ${value}`),
558
+ ...module.secrets
559
+ .filter((value) => value.required &&
560
+ (!value.environments || value.environments.includes(environment)))
561
+ .map((value) => `${value.name} is required in ${environment} runtime configuration`),
562
+ ...module.capabilities
563
+ .filter((value) => value.endsWith(".create"))
564
+ .map((value) => `${value} requires an explicit authorization policy`),
565
+ ]);
61
566
  }
@@ -1,12 +1,15 @@
1
1
  import { type FeltDBContractSnapshot } from './application-development.js';
2
+ import { type ApplicationUnderstanding, type ObservedEvidenceInput } from './application-understanding.js';
2
3
  export declare const FELTDB_PROPOSAL_COLLECTION = "_feltdb.Proposal";
3
4
  export declare const FELTDB_PROPOSAL_EVENT_COLLECTION = "_feltdb.ProposalEvent";
4
5
  export declare const FELTDB_PROPOSAL_PREVIEW_COLLECTION = "_feltdb.ProposalPreview";
6
+ export declare const FELTDB_CONVERGENCE_COLLECTION = "_feltdb.Convergence";
5
7
  export declare const FELTDB_PROPOSAL_VERSION = 1;
6
8
  export type ProposalStatus = 'proposed' | 'validated' | 'previewed' | 'approved' | 'applied' | 'rejected' | 'expired';
7
9
  export interface ProposalSourceOperation {
8
10
  path: string;
9
11
  operation: 'add' | 'modify' | 'delete';
12
+ role?: string;
10
13
  }
11
14
  export interface FeltDBProposalRecord {
12
15
  id: string;
@@ -43,6 +46,9 @@ export interface FeltDBProposalRecord {
43
46
  provider: string;
44
47
  version: string;
45
48
  }[];
49
+ evidence_hash?: string;
50
+ understanding_hash?: string;
51
+ understanding?: ApplicationUnderstanding;
46
52
  module_impact: {
47
53
  modules: string[];
48
54
  models: string[];
@@ -69,7 +75,7 @@ export interface FeltDBProposalEvent {
69
75
  export interface ProposalReadiness {
70
76
  status: ProposalStatus;
71
77
  readiness: 'ready' | 'blocked';
72
- blockers: ('contract_changed' | 'flow_changed' | 'module_versions_changed' | 'expired')[];
78
+ blockers: ('contract_changed' | 'flow_changed' | 'module_versions_changed' | 'evidence_changed' | 'expired')[];
73
79
  notes: string[];
74
80
  current_contract_hash: string;
75
81
  proposal_contract_hash: string;
@@ -127,6 +133,7 @@ export interface ProposalStore {
127
133
  export interface ProposalContext {
128
134
  source: string;
129
135
  snapshot: FeltDBContractSnapshot;
136
+ observations?: ObservedEvidenceInput[];
130
137
  }
131
138
  export declare class FeltDBProposalService {
132
139
  private store;
@@ -145,6 +152,11 @@ export declare class FeltDBProposalService {
145
152
  metadata?: Record<string, string>;
146
153
  parent_proposal_id?: string;
147
154
  expires_at?: string | number;
155
+ understanding?: ApplicationUnderstanding;
156
+ contract_diff?: string[];
157
+ source_plan?: {
158
+ files: ProposalSourceOperation[];
159
+ };
148
160
  }): Promise<FeltDBProposalRecord>;
149
161
  list(): Promise<FeltDBProposalRecord[]>;
150
162
  get(id: string): Promise<FeltDBProposalRecord>;