@feltdb/core 0.7.4 → 0.8.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.
- package/README.md +25 -0
- package/dist/application-development.d.ts +3 -1
- package/dist/application-development.d.ts.map +1 -1
- package/dist/application-development.js +16 -0
- package/dist/application-manifest.d.ts +1 -0
- package/dist/application-manifest.d.ts.map +1 -1
- package/dist/canonical-application.d.ts +1 -0
- package/dist/canonical-application.d.ts.map +1 -1
- package/dist/canonical-application.js +3 -2
- package/dist/cli/cli.js +1 -1
- package/dist/cli/commands.js +225 -42
- package/dist/cli/index.js +1 -1
- package/dist/cli/managed-environment.js +6 -0
- package/dist/cli/managed-project.js +6 -0
- package/dist/cli/proposal-client.js +12 -3
- package/dist/cli/publish-engine.js +7 -4
- package/dist/cli/source-sync.js +47 -3
- package/dist/create/cli.js +10 -1
- package/dist/create/create.js +10 -12
- package/dist/create/managed-account.js +71 -7
- package/dist/create/package-versions.js +1 -1
- package/dist/create/server-source/crates/feltdb/src/application.rs +10 -0
- package/dist/create/server-source/crates/feltdb/src/lib.rs +20 -2
- package/dist/create/server-source/crates/feltdb-server/src/app_state.rs +12 -24
- package/dist/create/server-source/crates/feltdb-server/src/application_contract.rs +11 -3
- package/dist/create/server-source/crates/feltdb-server/src/authenticated_principal.rs +0 -1
- package/dist/create/server-source/crates/feltdb-server/src/certification_harness.rs +23 -22
- package/dist/create/server-source/crates/feltdb-server/src/delegation_token.rs +5 -15
- package/dist/create/server-source/crates/feltdb-server/src/durable_operations.rs +13 -28
- package/dist/create/server-source/crates/feltdb-server/src/identity.rs +79 -14
- package/dist/create/server-source/crates/feltdb-server/src/key_management.rs +28 -7
- package/dist/create/server-source/crates/feltdb-server/src/lib.rs +5 -5
- package/dist/create/server-source/crates/feltdb-server/src/main.rs +1777 -259
- package/dist/create/server-source/crates/feltdb-server/src/managed_diagnostics.rs +10 -30
- package/dist/create/server-source/crates/feltdb-server/src/membership_policy.rs +12 -4
- package/dist/create/server-source/crates/feltdb-server/src/request_telemetry.rs +8 -6
- package/dist/create/server-source/crates/feltdb-server/src/snapshot_cursor.rs +10 -14
- package/dist/create/server-source/crates/feltdb-server/src/tenancy.rs +183 -21
- package/dist/create/server-source/crates/feltdb-server/src/tenant_policies.rs +9 -21
- package/dist/create/server-source/crates/feltdb-server/src/transaction_idempotency.rs +5 -3
- package/dist/create/server-source/crates/feltdb-server/src/transaction_recovery.rs +9 -8
- package/dist/create/server-source/crates/feltdb-server/tests/revision_recovery_integration_test.rs +1 -4
- package/dist/create/template/default-project/feltdb.flow +5 -0
- package/dist/flowspec.d.ts +1 -0
- package/dist/flowspec.d.ts.map +1 -1
- package/dist/flowspec.js +46 -12
- package/dist/http-client.d.ts +135 -14
- package/dist/http-client.d.ts.map +1 -1
- package/dist/http-client.js +79 -31
- package/dist/index-core.d.ts +2 -0
- package/dist/index-core.d.ts.map +1 -1
- package/dist/index-core.js +2 -0
- package/dist/module-intent.d.ts +37 -0
- package/dist/module-intent.d.ts.map +1 -0
- package/dist/module-intent.js +81 -0
- package/dist/module.d.ts +76 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +61 -0
- package/dist/proposal.d.ts +80 -4
- package/dist/proposal.d.ts.map +1 -1
- package/dist/proposal.js +132 -5
- package/dist/studio/app.d.ts +3 -1
- package/dist/studio/app.d.ts.map +1 -1
- package/dist/studio/components/AskFeltDB.d.ts +2 -1
- package/dist/studio/components/AskFeltDB.d.ts.map +1 -1
- package/dist/studio/components/ContractInspector.d.ts +7 -0
- package/dist/studio/components/ContractInspector.d.ts.map +1 -0
- package/dist/studio/components/ManagedInstancePanel.d.ts.map +1 -1
- package/dist/studio/components/ManagedInstancePanel.js +1 -5
- package/dist/studio/components/ModuleExplorer.d.ts +6 -0
- package/dist/studio/components/ModuleExplorer.d.ts.map +1 -0
- package/dist/studio/components/ProposalBrowser.d.ts +10 -1
- package/dist/studio/components/ProposalBrowser.d.ts.map +1 -1
- package/dist/studio/components/StateExplorer.d.ts +6 -7
- package/dist/studio/components/StateExplorer.d.ts.map +1 -1
- package/dist/studio/components/index.d.ts +2 -0
- package/dist/studio/components/index.d.ts.map +1 -1
- package/dist/studio/components/index.js +4 -4
- package/dist/studio/components-CNSNrmA9.js +2787 -0
- package/dist/studio/index.js +193 -147
- package/dist/studio/studio.css +1 -1
- package/dist/studio/utils/index.d.ts +2 -0
- package/dist/studio/utils/index.d.ts.map +1 -1
- package/dist/studio/utils/index.js +14 -12
- package/dist/studio/utils/managed-instance.d.ts +0 -4
- package/dist/studio/utils/managed-instance.d.ts.map +1 -1
- package/dist/studio/utils/managed-instance.js +0 -4
- package/dist/studio/utils/proposal-api.d.ts +53 -0
- package/dist/studio/utils/proposal-api.d.ts.map +1 -0
- package/dist/studio/utils/proposal-api.js +91 -0
- package/dist/studio/utils/service-api.d.ts +81 -0
- package/dist/studio/utils/service-api.d.ts.map +1 -0
- package/dist/studio/utils/service-api.js +51 -0
- package/dist/studio-app/assets/{dist-DA1MYSzp.js → dist-CCOk39Uc.js} +1 -1
- package/dist/studio-app/assets/{feltdb_wasm-B-Ccgccb.js → feltdb_wasm-CSB6KVgw.js} +1 -1
- package/dist/studio-app/assets/feltdb_wasm_bg-Dd1fnO9U.wasm +0 -0
- package/dist/studio-app/assets/index-Bncji3aN.js +43 -0
- package/dist/studio-app/assets/{index-BRrmvaKw.css → index-yazaWMUN.css} +1 -1
- package/dist/studio-app/index.html +2 -2
- package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
- package/dist/workspace/local-development-authority.d.ts.map +1 -1
- package/dist/workspace/local-development-authority.js +64 -3
- package/package.json +1 -1
- package/dist/studio/components-Bm4sjhcX.js +0 -2162
- package/dist/studio-app/assets/feltdb_wasm_bg-wH3enJIA.wasm +0 -0
- package/dist/studio-app/assets/index-CEIqowCh.js +0 -42
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { formatFlowSpec, parseFlowSpec } from './flowspec.js';
|
|
2
|
+
import { findFeltDBModules, listFeltDBModules, resolveFeltDBModule } from './module.js';
|
|
3
|
+
async function sourceHash(source) {
|
|
4
|
+
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(source.replace(/\r\n/g, '\n')));
|
|
5
|
+
return `sha256:${Array.from(new Uint8Array(digest), byte => byte.toString(16).padStart(2, '0')).join('')}`;
|
|
6
|
+
}
|
|
7
|
+
export function resolveModuleIntent(value) {
|
|
8
|
+
const match = /^\s*implement\s+([a-z0-9][a-z0-9-]*)\s*[.!]?\s*$/i.exec(value);
|
|
9
|
+
const incrementalBilling = /^\s*(?:add|support|enable)\b.+\b(?:billing|plan|subscription)\b.*$/i.test(value);
|
|
10
|
+
if (!match && !incrementalBilling)
|
|
11
|
+
return undefined;
|
|
12
|
+
const requested = match ? match[1].toLowerCase() : 'billing';
|
|
13
|
+
const matches = findFeltDBModules(requested);
|
|
14
|
+
if (!matches.length)
|
|
15
|
+
throw new Error(`MODULE_NOT_AVAILABLE: ${requested}. No proposal created. Available modules: ${listFeltDBModules().map(module => module.id).join(', ')}`);
|
|
16
|
+
if (matches.length > 1)
|
|
17
|
+
throw new Error(`AMBIGUOUS_MODULE_INTENT: ${requested}. Available providers: ${matches.map(module => module.provider).join(', ')}`);
|
|
18
|
+
const module = matches[0];
|
|
19
|
+
return { action: match ? 'implement' : 'extend', module: module.id, provider: module.provider, version: module.version, original: value };
|
|
20
|
+
}
|
|
21
|
+
function billingOwner(spec, module) {
|
|
22
|
+
const names = new Set(spec.collections.map(collection => collection.name));
|
|
23
|
+
for (const pattern of module.patterns)
|
|
24
|
+
for (const candidate of pattern.owner_candidates)
|
|
25
|
+
if (names.has(candidate))
|
|
26
|
+
return candidate;
|
|
27
|
+
return spec.collections.find(collection => /user|account|member/i.test(collection.name))?.name ?? spec.collections[0]?.name ?? 'User';
|
|
28
|
+
}
|
|
29
|
+
export function planModuleImplementation(intent, snapshot, currentFlow) {
|
|
30
|
+
const module = resolveFeltDBModule({ name: intent.module, provider: intent.provider, version: intent.version });
|
|
31
|
+
const spec = parseFlowSpec(currentFlow);
|
|
32
|
+
const owner = billingOwner(spec, module);
|
|
33
|
+
const alreadyInstalled = Boolean(spec.modules?.some(value => value.name === module.id));
|
|
34
|
+
const pattern = module.patterns.find(value => value.owner_candidates.includes(owner)) ?? module.patterns[0];
|
|
35
|
+
const implementedEvents = new Set(spec.triggers.map(value => value.event));
|
|
36
|
+
const implementedWorkflows = new Set(spec.workflows.map(value => value.name));
|
|
37
|
+
return { intent, module, alreadyInstalled, owner, applicationModels: pattern.application_models,
|
|
38
|
+
relationships: [`BillingAccount.owner -> ${owner}`, `BillingAccount.customer -> ${module.id}.Customer`, `BillingAccount.subscription -> ${module.id}.Subscription`, `Entitlement.billing_account -> BillingAccount`],
|
|
39
|
+
events: module.reconciliation.map(value => value.event).filter(value => !implementedEvents.has(value)),
|
|
40
|
+
workflows: module.reconciliation.map(value => value.workflow).filter(value => !implementedWorkflows.has(value)),
|
|
41
|
+
capabilities: ['stripe.checkout.create', 'stripe.subscription.read', 'stripe.subscription.cancel'].filter(value => module.capabilities.includes(value)),
|
|
42
|
+
authorization: module.authorization, configuration: module.configuration.map(value => value.name), secrets: module.secrets.map(value => value.name),
|
|
43
|
+
stateFlow: [`${module.id}.subscription.updated`, `ReconcileSubscription`, `BillingAccount`, `Entitlement`],
|
|
44
|
+
warnings: ['Production webhook configuration and signature verification required'],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function addCollection(spec, collection) { if (!spec.collections.some(value => value.name === collection.name))
|
|
48
|
+
spec.collections.push(collection); }
|
|
49
|
+
export async function createModuleImplementationProposal(input) {
|
|
50
|
+
const resolved = resolveModuleIntent(input.intent);
|
|
51
|
+
if (!resolved)
|
|
52
|
+
throw new Error('NOT_A_MODULE_INTENT');
|
|
53
|
+
const plan = planModuleImplementation(resolved, input.snapshot, input.currentFlow);
|
|
54
|
+
const spec = parseFlowSpec(input.currentFlow);
|
|
55
|
+
if (resolved.action === 'extend' && !plan.alreadyInstalled)
|
|
56
|
+
throw new Error(`MODULE_NOT_INSTALLED: ${plan.module.id}. Run implement ${plan.module.id} first.`);
|
|
57
|
+
if (!spec.modules?.some(value => value.name === plan.module.id))
|
|
58
|
+
spec.modules.push({ name: plan.module.id, provider: plan.module.provider, version: plan.module.version });
|
|
59
|
+
addCollection(spec, { name: 'BillingAccount', fields: [
|
|
60
|
+
{ name: 'owner', type: `ref ${plan.owner}`, optional: false }, { name: 'customer', type: `ref ${plan.module.id}.Customer`, optional: false },
|
|
61
|
+
{ name: 'subscription', type: `ref ${plan.module.id}.Subscription`, optional: true }, { name: 'status', type: 'text', optional: false },
|
|
62
|
+
], indexes: [] });
|
|
63
|
+
addCollection(spec, { name: 'Entitlement', fields: [{ name: 'billing_account', type: 'ref BillingAccount', optional: false }, { name: 'key', type: 'text', optional: false }, { name: 'active', type: 'boolean', optional: false }], indexes: [] });
|
|
64
|
+
if (resolved.action === 'extend')
|
|
65
|
+
addCollection(spec, { name: 'BillingPlan', fields: [
|
|
66
|
+
{ name: 'code', type: 'text', optional: false }, { name: 'interval', type: 'enum(monthly,annual)', optional: false },
|
|
67
|
+
{ name: 'price', type: `ref ${plan.module.id}.Price`, optional: false }, { name: 'active', type: 'boolean', optional: false },
|
|
68
|
+
], indexes: [] });
|
|
69
|
+
for (const reconciliation of plan.module.reconciliation) {
|
|
70
|
+
if (!spec.workflows.some(value => value.name === reconciliation.workflow))
|
|
71
|
+
spec.workflows.push({ name: reconciliation.workflow, parameters: '', steps: [{ name: 'reconcile', statements: ['read BillingAccount', 'write BillingAccount', 'write Entitlement', `capability ${plan.module.id}.subscription.read`] }] });
|
|
72
|
+
if (!spec.triggers.some(value => value.event === reconciliation.event))
|
|
73
|
+
spec.triggers.push({ event: reconciliation.event, statements: [`run ${reconciliation.workflow}`] });
|
|
74
|
+
}
|
|
75
|
+
if (!spec.policies.some(value => value.name === 'BillingAccount'))
|
|
76
|
+
spec.policies.push({ name: 'BillingAccount', statements: ['read: owner', 'write: owner'] });
|
|
77
|
+
const prefix = resolved.action === 'extend' ? 'Extend' : plan.alreadyInstalled ? 'Complete' : 'Implement';
|
|
78
|
+
return { baseContractHash: input.snapshot.contract_hash, baseFlowHash: await sourceHash(input.currentFlow), proposedFlow: formatFlowSpec(spec),
|
|
79
|
+
summary: `${prefix} ${plan.module.name}`, changes: [...(resolved.action === 'extend' ? ['BillingPlan (application-authoritative)', 'BillingPlan.price -> stripe.Price'] : plan.applicationModels.map(value => `${value.name} (${value.ownership})`)), ...plan.relationships, ...plan.workflows, ...plan.capabilities],
|
|
80
|
+
warnings: [...plan.warnings, ...(resolved.action === 'extend' ? ['Plan and price records must be configured through application data; no provider values were invented'] : [])], implementation: plan };
|
|
81
|
+
}
|
package/dist/module.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export type FeltDBModuleOwnership = 'external-authoritative' | 'application-authoritative' | 'derived' | 'synchronized';
|
|
2
|
+
export interface FeltDBModuleModel {
|
|
3
|
+
name: string;
|
|
4
|
+
authority: 'external';
|
|
5
|
+
ownership: FeltDBModuleOwnership;
|
|
6
|
+
fields: {
|
|
7
|
+
name: string;
|
|
8
|
+
type: string;
|
|
9
|
+
optional?: boolean;
|
|
10
|
+
immutable?: boolean;
|
|
11
|
+
externally_owned?: boolean;
|
|
12
|
+
application_readable?: boolean;
|
|
13
|
+
}[];
|
|
14
|
+
}
|
|
15
|
+
export interface FeltDBModuleRelationship {
|
|
16
|
+
from: string;
|
|
17
|
+
to: string;
|
|
18
|
+
kind: 'one' | 'many';
|
|
19
|
+
}
|
|
20
|
+
export interface FeltDBModuleRequirement {
|
|
21
|
+
name: string;
|
|
22
|
+
required: boolean;
|
|
23
|
+
environments?: string[];
|
|
24
|
+
description: string;
|
|
25
|
+
}
|
|
26
|
+
export interface FeltDBModulePattern {
|
|
27
|
+
name: string;
|
|
28
|
+
when: string;
|
|
29
|
+
owner_candidates: string[];
|
|
30
|
+
application_models: Array<{
|
|
31
|
+
name: string;
|
|
32
|
+
ownership: FeltDBModuleOwnership;
|
|
33
|
+
purpose: string;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
export interface FeltDBModuleReconciliation {
|
|
37
|
+
event: string;
|
|
38
|
+
workflow: string;
|
|
39
|
+
reads: string[];
|
|
40
|
+
writes: string[];
|
|
41
|
+
outcome: string;
|
|
42
|
+
}
|
|
43
|
+
export interface FeltDBModuleDefinition {
|
|
44
|
+
id: string;
|
|
45
|
+
name: string;
|
|
46
|
+
version: string;
|
|
47
|
+
provider: string;
|
|
48
|
+
compatibility: string[];
|
|
49
|
+
models: FeltDBModuleModel[];
|
|
50
|
+
relationships: FeltDBModuleRelationship[];
|
|
51
|
+
events: string[];
|
|
52
|
+
capabilities: string[];
|
|
53
|
+
workflows: string[];
|
|
54
|
+
configuration: FeltDBModuleRequirement[];
|
|
55
|
+
secrets: FeltDBModuleRequirement[];
|
|
56
|
+
validation: string[];
|
|
57
|
+
dependencies: string[];
|
|
58
|
+
authorization: Array<{
|
|
59
|
+
capability: string;
|
|
60
|
+
subject: string;
|
|
61
|
+
implication: string;
|
|
62
|
+
}>;
|
|
63
|
+
patterns: FeltDBModulePattern[];
|
|
64
|
+
reconciliation: FeltDBModuleReconciliation[];
|
|
65
|
+
}
|
|
66
|
+
export interface FlowModuleDeclaration {
|
|
67
|
+
name: string;
|
|
68
|
+
provider: string;
|
|
69
|
+
version?: string;
|
|
70
|
+
}
|
|
71
|
+
export declare function listFeltDBModules(): FeltDBModuleDefinition[];
|
|
72
|
+
export declare function resolveFeltDBModule(declaration: FlowModuleDeclaration): FeltDBModuleDefinition;
|
|
73
|
+
export declare function findFeltDBModules(query: string): FeltDBModuleDefinition[];
|
|
74
|
+
export declare function resolveFeltDBModules(declarations?: FlowModuleDeclaration[]): FeltDBModuleDefinition[];
|
|
75
|
+
export declare function validateResolvedModules(modules: FeltDBModuleDefinition[], environment?: string): string[];
|
|
76
|
+
//# sourceMappingURL=module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"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"}
|
package/dist/module.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
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
|
+
] })),
|
|
11
|
+
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: [],
|
|
23
|
+
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' },
|
|
26
|
+
],
|
|
27
|
+
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
|
+
] },
|
|
36
|
+
],
|
|
37
|
+
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' },
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
const definitions = new Map([[stripe.id, stripe]]);
|
|
43
|
+
export function listFeltDBModules() { return [...definitions.values()].map(value => structuredClone(value)); }
|
|
44
|
+
export function resolveFeltDBModule(declaration) {
|
|
45
|
+
const definition = definitions.get(declaration.name);
|
|
46
|
+
if (!definition)
|
|
47
|
+
throw new Error(`UNKNOWN_MODULE: ${declaration.name}`);
|
|
48
|
+
if (!definition.compatibility.includes(declaration.provider))
|
|
49
|
+
throw new Error(`INCOMPATIBLE_MODULE_PROVIDER: ${declaration.name} does not support ${declaration.provider}`);
|
|
50
|
+
if (declaration.version && declaration.version !== definition.version)
|
|
51
|
+
throw new Error(`INCOMPATIBLE_MODULE_VERSION: ${declaration.name}@${declaration.version}; available ${definition.version}`);
|
|
52
|
+
return { ...structuredClone(definition), provider: declaration.provider };
|
|
53
|
+
}
|
|
54
|
+
export function findFeltDBModules(query) {
|
|
55
|
+
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)));
|
|
57
|
+
}
|
|
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`)]);
|
|
61
|
+
}
|
package/dist/proposal.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type FeltDBContractSnapshot } from './application-development.js';
|
|
2
2
|
export declare const FELTDB_PROPOSAL_COLLECTION = "_feltdb.Proposal";
|
|
3
3
|
export declare const FELTDB_PROPOSAL_EVENT_COLLECTION = "_feltdb.ProposalEvent";
|
|
4
|
+
export declare const FELTDB_PROPOSAL_PREVIEW_COLLECTION = "_feltdb.ProposalPreview";
|
|
4
5
|
export declare const FELTDB_PROPOSAL_VERSION = 1;
|
|
5
6
|
export type ProposalStatus = 'proposed' | 'validated' | 'previewed' | 'approved' | 'applied' | 'rejected' | 'expired';
|
|
6
7
|
export interface ProposalSourceOperation {
|
|
@@ -28,9 +29,33 @@ export interface FeltDBProposalRecord {
|
|
|
28
29
|
approved_by?: string;
|
|
29
30
|
approved_at?: string | number;
|
|
30
31
|
applied_at?: string | number;
|
|
32
|
+
preview_id?: string;
|
|
31
33
|
expires_at?: string | number;
|
|
32
34
|
metadata: Record<string, string>;
|
|
33
35
|
parent_proposal_id?: string;
|
|
36
|
+
module_versions: {
|
|
37
|
+
id: string;
|
|
38
|
+
provider: string;
|
|
39
|
+
version: string;
|
|
40
|
+
}[];
|
|
41
|
+
base_module_versions?: {
|
|
42
|
+
id: string;
|
|
43
|
+
provider: string;
|
|
44
|
+
version: string;
|
|
45
|
+
}[];
|
|
46
|
+
module_impact: {
|
|
47
|
+
modules: string[];
|
|
48
|
+
models: string[];
|
|
49
|
+
relationships: string[];
|
|
50
|
+
events: string[];
|
|
51
|
+
workflows: string[];
|
|
52
|
+
capabilities: string[];
|
|
53
|
+
authorization: string[];
|
|
54
|
+
configuration: string[];
|
|
55
|
+
secrets: string[];
|
|
56
|
+
ownership: Record<string, string>;
|
|
57
|
+
state_flow: string[];
|
|
58
|
+
};
|
|
34
59
|
}
|
|
35
60
|
export interface FeltDBProposalEvent {
|
|
36
61
|
id: string;
|
|
@@ -41,6 +66,58 @@ export interface FeltDBProposalEvent {
|
|
|
41
66
|
created_at: string | number;
|
|
42
67
|
metadata: Record<string, string>;
|
|
43
68
|
}
|
|
69
|
+
export interface ProposalReadiness {
|
|
70
|
+
status: ProposalStatus;
|
|
71
|
+
readiness: 'ready' | 'blocked';
|
|
72
|
+
blockers: ('contract_changed' | 'flow_changed' | 'module_versions_changed' | 'expired')[];
|
|
73
|
+
notes: string[];
|
|
74
|
+
current_contract_hash: string;
|
|
75
|
+
proposal_contract_hash: string;
|
|
76
|
+
current_flow_hash: string;
|
|
77
|
+
proposal_flow_hash: string;
|
|
78
|
+
stale: boolean;
|
|
79
|
+
expires_at?: string | number;
|
|
80
|
+
}
|
|
81
|
+
export interface FeltDBProposalPreviewArtifact {
|
|
82
|
+
preview_id: string;
|
|
83
|
+
proposal_id: string;
|
|
84
|
+
application_id: string;
|
|
85
|
+
environment: string;
|
|
86
|
+
proposal_hash: string;
|
|
87
|
+
created_at: string;
|
|
88
|
+
expires_at: string;
|
|
89
|
+
status: 'ready';
|
|
90
|
+
current: FeltDBContractSnapshot;
|
|
91
|
+
proposed: FeltDBContractSnapshot;
|
|
92
|
+
current_contract: FeltDBContractSnapshot;
|
|
93
|
+
proposed_contract: FeltDBContractSnapshot;
|
|
94
|
+
semantic_diff: string[];
|
|
95
|
+
state_flow: string[];
|
|
96
|
+
capabilities: unknown[];
|
|
97
|
+
workflows: unknown[];
|
|
98
|
+
authorization: unknown[];
|
|
99
|
+
configuration: string[];
|
|
100
|
+
secrets: string[];
|
|
101
|
+
modules: string[];
|
|
102
|
+
ownership: Record<string, string>;
|
|
103
|
+
relationships: string[];
|
|
104
|
+
events: string[];
|
|
105
|
+
seeded_records: {
|
|
106
|
+
collection: string;
|
|
107
|
+
id: string;
|
|
108
|
+
preview_data: true;
|
|
109
|
+
}[];
|
|
110
|
+
data_classification: 'synthetic_preview';
|
|
111
|
+
external_side_effects: 'simulated';
|
|
112
|
+
readiness: ProposalReadiness;
|
|
113
|
+
proposal: FeltDBProposalRecord;
|
|
114
|
+
}
|
|
115
|
+
/** Canonical human diagnostic used by CLI and Studio text surfaces. */
|
|
116
|
+
export declare function renderProposalDiagnostic(proposal: FeltDBProposalRecord, options?: {
|
|
117
|
+
readiness?: ProposalReadiness;
|
|
118
|
+
history?: FeltDBProposalEvent[];
|
|
119
|
+
preview?: FeltDBProposalPreviewArtifact;
|
|
120
|
+
}): string[];
|
|
44
121
|
export interface ProposalStore {
|
|
45
122
|
get<T>(collection: string, id: string): Promise<T | undefined>;
|
|
46
123
|
list<T>(collection: string): Promise<T[]>;
|
|
@@ -72,11 +149,10 @@ export declare class FeltDBProposalService {
|
|
|
72
149
|
list(): Promise<FeltDBProposalRecord[]>;
|
|
73
150
|
get(id: string): Promise<FeltDBProposalRecord>;
|
|
74
151
|
history(id: string): Promise<FeltDBProposalEvent[]>;
|
|
152
|
+
readiness(id: string): Promise<ProposalReadiness>;
|
|
75
153
|
validate(id: string, actor: string): Promise<FeltDBProposalRecord>;
|
|
76
|
-
preview(id: string, actor: string): Promise<
|
|
77
|
-
|
|
78
|
-
contract: FeltDBContractSnapshot;
|
|
79
|
-
}>;
|
|
154
|
+
preview(id: string, actor: string): Promise<FeltDBProposalPreviewArtifact>;
|
|
155
|
+
getPreview(id: string): Promise<FeltDBProposalPreviewArtifact>;
|
|
80
156
|
transition(id: string, status: 'approved' | 'rejected' | 'expired' | 'applied', actor: string, authority?: string, approveAuthorization?: boolean): Promise<FeltDBProposalRecord>;
|
|
81
157
|
private assertMutable;
|
|
82
158
|
private move;
|
package/dist/proposal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proposal.d.ts","sourceRoot":"","sources":["../src/proposal.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,sBAAsB,EAE5B,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"proposal.d.ts","sourceRoot":"","sources":["../src/proposal.ts"],"names":[],"mappings":"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"}
|
package/dist/proposal.js
CHANGED
|
@@ -1,7 +1,53 @@
|
|
|
1
1
|
import { createContractSnapshot, flowSourceHash, validateFlowProposal, } from './application-development.js';
|
|
2
|
+
import { validateResolvedModules } from './module.js';
|
|
2
3
|
export const FELTDB_PROPOSAL_COLLECTION = '_feltdb.Proposal';
|
|
3
4
|
export const FELTDB_PROPOSAL_EVENT_COLLECTION = '_feltdb.ProposalEvent';
|
|
5
|
+
export const FELTDB_PROPOSAL_PREVIEW_COLLECTION = '_feltdb.ProposalPreview';
|
|
4
6
|
export const FELTDB_PROPOSAL_VERSION = 1;
|
|
7
|
+
function redactProposalSecretValues(input) {
|
|
8
|
+
const visit = (value, key = '') => {
|
|
9
|
+
if (value === null || value === undefined)
|
|
10
|
+
return value;
|
|
11
|
+
if (typeof value === 'string')
|
|
12
|
+
return /(?:sk_(?:live|test)_|whsec_|-----BEGIN PRIVATE KEY-----)/.test(value) ? '[REDACTED]' : value;
|
|
13
|
+
if (Array.isArray(value))
|
|
14
|
+
return value.map(item => visit(item));
|
|
15
|
+
if (typeof value === 'object')
|
|
16
|
+
return Object.fromEntries(Object.entries(value).map(([name, child]) => [/secret|password|token|api_?key|credential|private_?key/i.test(name) ? name : name, /secret|password|token|api_?key|credential|private_?key/i.test(name) ? '[REDACTED]' : visit(child, name)]));
|
|
17
|
+
return /secret|password|token|api_?key|credential|private_?key/i.test(key) ? '[REDACTED]' : value;
|
|
18
|
+
};
|
|
19
|
+
return visit(structuredClone(input));
|
|
20
|
+
}
|
|
21
|
+
/** Canonical human diagnostic used by CLI and Studio text surfaces. */
|
|
22
|
+
export function renderProposalDiagnostic(proposal, options = {}) {
|
|
23
|
+
const impact = proposal.module_impact;
|
|
24
|
+
const section = (name, values) => values.length ? [name, ...values.map(value => ` ${value}`)] : [];
|
|
25
|
+
const readiness = options.readiness;
|
|
26
|
+
return [
|
|
27
|
+
`Proposal: ${proposal.id}`,
|
|
28
|
+
proposal.summary,
|
|
29
|
+
`Status ${proposal.status.toUpperCase()}`,
|
|
30
|
+
`Application ${proposal.application_id}`,
|
|
31
|
+
`Environment ${proposal.environment}`,
|
|
32
|
+
`Contract v${proposal.base_contract_version} ${proposal.base_contract_hash}`,
|
|
33
|
+
`Flow ${proposal.base_flow_hash}`,
|
|
34
|
+
...(proposal.parent_proposal_id ? [`Based on ${proposal.parent_proposal_id}`] : []),
|
|
35
|
+
...section('MODULES', proposal.module_versions.map(value => `+ ${value.id} (${value.provider}) ${value.version}`)),
|
|
36
|
+
...section('STATE', impact.models.map(value => `+ ${value}`)),
|
|
37
|
+
...section('RELATIONSHIPS', impact.relationships.map(value => `+ ${value}`)),
|
|
38
|
+
...section('WORKFLOWS', impact.workflows.map(value => `+ ${value}`)),
|
|
39
|
+
...section('EVENTS', impact.events.map(value => `+ ${value}`)),
|
|
40
|
+
...section('CAPABILITIES', impact.capabilities.map(value => `+ ${value}`)),
|
|
41
|
+
...section('AUTHORIZATION', impact.authorization.map(value => `+ ${value}`)),
|
|
42
|
+
...section('CONFIGURATION', [...impact.configuration.map(value => `${value} configuration`), ...impact.secrets.map(value => `${value} required / secret`)]),
|
|
43
|
+
...(readiness ? ['READINESS',
|
|
44
|
+
` ${readiness.stale ? '!' : '✓'} Contract and flow ${readiness.stale ? 'stale' : 'current'}`,
|
|
45
|
+
` ${readiness.blockers.length ? readiness.blockers.join(', ') : 'No blockers'}`] : []),
|
|
46
|
+
...(options.preview ? ['PREVIEW', ' Current → Proposed available', ` ${options.preview.preview_id}`] : []),
|
|
47
|
+
...section('HISTORY', (options.history ?? []).map(value => `✓ ${value.to_status}`)),
|
|
48
|
+
...section('WARNINGS', proposal.warnings.map(value => `! ${value}`)),
|
|
49
|
+
];
|
|
50
|
+
}
|
|
5
51
|
const transitions = {
|
|
6
52
|
proposed: ['validated', 'rejected'], validated: ['previewed', 'rejected'], previewed: ['approved', 'rejected'],
|
|
7
53
|
approved: ['applied', 'expired'], applied: [], rejected: [], expired: [],
|
|
@@ -22,11 +68,15 @@ export class FeltDBProposalService {
|
|
|
22
68
|
if (input.base_contract_hash !== current.snapshot.contract_hash || input.base_flow_hash !== await flowSourceHash(current.source))
|
|
23
69
|
throw new Error('STALE_PROPOSAL');
|
|
24
70
|
const id = `p_${crypto.randomUUID().replace(/-/g, '')}`;
|
|
25
|
-
const
|
|
71
|
+
const safeInput = redactProposalSecretValues(input);
|
|
72
|
+
const record = { id, application_id: safeInput.application_id, environment: safeInput.environment,
|
|
26
73
|
status: 'proposed', proposal_version: FELTDB_PROPOSAL_VERSION, base_contract_version: current.snapshot.contract_version,
|
|
27
|
-
base_contract_hash:
|
|
28
|
-
contract_diff: [], source_plan: { files: [] }, summary:
|
|
29
|
-
created_at: new Date().toISOString(), expires_at:
|
|
74
|
+
base_contract_hash: safeInput.base_contract_hash, base_flow_hash: safeInput.base_flow_hash, proposed_flow: safeInput.proposed_flow,
|
|
75
|
+
contract_diff: [], source_plan: { files: [] }, summary: safeInput.summary, warnings: safeInput.warnings ?? [], created_by: safeInput.actor,
|
|
76
|
+
created_at: new Date().toISOString(), expires_at: safeInput.expires_at, metadata: safeInput.metadata ?? {}, parent_proposal_id: safeInput.parent_proposal_id,
|
|
77
|
+
base_module_versions: current.snapshot.modules.map(value => ({ id: value.id, provider: value.provider, version: value.version })),
|
|
78
|
+
module_versions: current.snapshot.modules.map(value => ({ id: value.id, provider: value.provider, version: value.version })),
|
|
79
|
+
module_impact: { modules: [], models: [], relationships: [], events: [], workflows: [], capabilities: [], authorization: [], configuration: [], secrets: [], ownership: {}, state_flow: [] } };
|
|
30
80
|
await this.store.create(FELTDB_PROPOSAL_COLLECTION, id, record);
|
|
31
81
|
await this.event(id, undefined, 'proposed', input.actor);
|
|
32
82
|
return record;
|
|
@@ -41,6 +91,25 @@ export class FeltDBProposalService {
|
|
|
41
91
|
async history(id) {
|
|
42
92
|
return (await this.store.list(FELTDB_PROPOSAL_EVENT_COLLECTION)).filter(value => value.proposal_id === id);
|
|
43
93
|
}
|
|
94
|
+
async readiness(id) {
|
|
95
|
+
const record = await this.get(id);
|
|
96
|
+
const current = await this.context();
|
|
97
|
+
const currentFlowHash = await flowSourceHash(current.source);
|
|
98
|
+
const currentModules = current.snapshot.modules.map(value => ({ id: value.id, provider: value.provider, version: value.version }));
|
|
99
|
+
const blockers = [];
|
|
100
|
+
if (record.base_contract_hash !== current.snapshot.contract_hash)
|
|
101
|
+
blockers.push('contract_changed');
|
|
102
|
+
if (record.base_flow_hash !== currentFlowHash)
|
|
103
|
+
blockers.push('flow_changed');
|
|
104
|
+
if (JSON.stringify(record.base_module_versions ?? []) !== JSON.stringify(currentModules))
|
|
105
|
+
blockers.push('module_versions_changed');
|
|
106
|
+
if (record.expires_at && (typeof record.expires_at === 'number' ? record.expires_at * 1000 : Date.parse(record.expires_at)) <= Date.now())
|
|
107
|
+
blockers.push('expired');
|
|
108
|
+
return { status: record.status, readiness: blockers.length ? 'blocked' : 'ready', blockers, notes: [],
|
|
109
|
+
current_contract_hash: current.snapshot.contract_hash, proposal_contract_hash: record.base_contract_hash,
|
|
110
|
+
current_flow_hash: currentFlowHash, proposal_flow_hash: record.base_flow_hash,
|
|
111
|
+
stale: blockers.some(value => value !== 'expired'), expires_at: record.expires_at };
|
|
112
|
+
}
|
|
44
113
|
async validate(id, actor) {
|
|
45
114
|
const record = await this.get(id);
|
|
46
115
|
this.assertMutable(record, 'proposed');
|
|
@@ -54,6 +123,22 @@ export class FeltDBProposalService {
|
|
|
54
123
|
];
|
|
55
124
|
record.source_plan = { files: [{ path: 'feltdb.flow', operation: 'modify' }, { path: 'src/feltdb/generated-contract.ts', operation: 'modify' }] };
|
|
56
125
|
record.warnings = [...new Set([...record.warnings, ...review.authorizationChanges.map(value => `Authorization ${value.widening ? 'widened' : 'changed'}: ${value.policy}: ${(value.before ?? []).join(' | ')} -> ${(value.after ?? []).join(' | ')}`)])];
|
|
126
|
+
record.warnings = [...new Set([...record.warnings, ...validateResolvedModules(review.proposedContract.manifest.modules ?? [], record.environment)])];
|
|
127
|
+
record.module_versions = (review.proposedContract.manifest.modules ?? []).map(value => ({ id: value.id, provider: value.provider, version: value.version }));
|
|
128
|
+
const moduleIds = new Set((review.proposedContract.manifest.modules ?? []).map(value => value.id));
|
|
129
|
+
record.module_impact = {
|
|
130
|
+
modules: [...moduleIds],
|
|
131
|
+
models: review.proposedSpec.collections.flatMap(collection => collection.fields.map(field => field.type.startsWith('ref ') ? field.type.slice(4) : '').filter(value => value.includes('.') && moduleIds.has(value.split('.')[0]))),
|
|
132
|
+
relationships: review.proposedSpec.collections.flatMap(collection => collection.fields.filter(field => field.type.startsWith('ref ')).map(field => `${collection.name}.${field.name} -> ${field.type.slice(4)}`)),
|
|
133
|
+
events: review.proposedSpec.triggers.map(value => value.event).filter(value => moduleIds.has(value.split('.')[0])),
|
|
134
|
+
workflows: review.proposedSpec.workflows.map(value => value.name),
|
|
135
|
+
capabilities: review.proposedContract.manifest.capabilities.filter(value => value.provider && moduleIds.has(value.provider)).map(value => value.name),
|
|
136
|
+
authorization: review.proposedSpec.policies.flatMap(value => value.statements.map(statement => `${value.name}: ${statement}`)),
|
|
137
|
+
configuration: (review.proposedContract.manifest.modules ?? []).flatMap(value => value.configuration.map(item => item.name)),
|
|
138
|
+
secrets: (review.proposedContract.manifest.modules ?? []).flatMap(value => value.secrets.map(item => item.name)),
|
|
139
|
+
ownership: Object.fromEntries((review.proposedContract.manifest.modules ?? []).flatMap(value => value.models.map(model => [`${value.id}.${model.name}`, model.ownership]))),
|
|
140
|
+
state_flow: (review.proposedContract.manifest.modules ?? []).flatMap(value => value.reconciliation.map(item => `${item.event} -> ${item.workflow} -> ${item.writes.join(', ')}`)),
|
|
141
|
+
};
|
|
57
142
|
return this.move(record, 'validated', actor);
|
|
58
143
|
}
|
|
59
144
|
async preview(id, actor) {
|
|
@@ -62,8 +147,40 @@ export class FeltDBProposalService {
|
|
|
62
147
|
const current = await this.context();
|
|
63
148
|
const review = await validateFlowProposal({ proposal: { baseContractHash: record.base_contract_hash, baseFlowHash: record.base_flow_hash,
|
|
64
149
|
proposedFlow: record.proposed_flow, summary: record.summary, changes: [], warnings: record.warnings }, currentFlow: current.source, snapshot: current.snapshot });
|
|
150
|
+
const proposed = createContractSnapshot(review.proposedContract, { environment: record.environment, contractVersion: record.base_contract_version + 1 });
|
|
151
|
+
const readiness = await this.readiness(id);
|
|
152
|
+
const now = Date.now();
|
|
153
|
+
const previewId = `pv_${crypto.randomUUID().replace(/-/g, '')}`;
|
|
65
154
|
await this.move(record, 'previewed', actor);
|
|
66
|
-
|
|
155
|
+
record.preview_id = previewId;
|
|
156
|
+
await this.store.replace(FELTDB_PROPOSAL_COLLECTION, record.id, record);
|
|
157
|
+
const impact = record.module_impact;
|
|
158
|
+
const artifact = {
|
|
159
|
+
preview_id: previewId, proposal_id: id, application_id: record.application_id, environment: record.environment,
|
|
160
|
+
proposal_hash: record.base_contract_hash, created_at: new Date(now).toISOString(), expires_at: new Date(now + 60 * 60 * 1000).toISOString(), status: 'ready',
|
|
161
|
+
current: current.snapshot, proposed, current_contract: current.snapshot, proposed_contract: proposed,
|
|
162
|
+
semantic_diff: record.contract_diff, state_flow: impact.state_flow, capabilities: proposed.capabilities, workflows: proposed.workflows,
|
|
163
|
+
authorization: proposed.policies, configuration: impact.configuration, secrets: impact.secrets, modules: impact.modules,
|
|
164
|
+
ownership: impact.ownership, relationships: impact.relationships, events: impact.events,
|
|
165
|
+
seeded_records: proposed.schema.map(collection => ({ collection: collection.name, id: `preview_${collection.name.toLowerCase()}`, preview_data: true })),
|
|
166
|
+
data_classification: 'synthetic_preview', external_side_effects: 'simulated', readiness, proposal: record,
|
|
167
|
+
};
|
|
168
|
+
await this.store.create(FELTDB_PROPOSAL_PREVIEW_COLLECTION, previewId, artifact);
|
|
169
|
+
return artifact;
|
|
170
|
+
}
|
|
171
|
+
async getPreview(id) {
|
|
172
|
+
const artifact = await this.store.get(FELTDB_PROPOSAL_PREVIEW_COLLECTION, id);
|
|
173
|
+
if (!artifact)
|
|
174
|
+
throw new Error('PREVIEW_NOT_FOUND');
|
|
175
|
+
if (Date.parse(artifact.expires_at) <= Date.now())
|
|
176
|
+
throw new Error('PREVIEW_EXPIRED');
|
|
177
|
+
const proposal = await this.get(artifact.proposal_id);
|
|
178
|
+
if (proposal.preview_id !== id)
|
|
179
|
+
throw new Error('PREVIEW_INVALIDATED');
|
|
180
|
+
const readiness = await this.readiness(proposal.id);
|
|
181
|
+
if (readiness.stale)
|
|
182
|
+
throw new Error('PREVIEW_INVALIDATED');
|
|
183
|
+
return artifact;
|
|
67
184
|
}
|
|
68
185
|
async transition(id, status, actor, authority, approveAuthorization = false) {
|
|
69
186
|
const record = await this.get(id);
|
|
@@ -72,6 +189,16 @@ export class FeltDBProposalService {
|
|
|
72
189
|
throw new Error('PROPOSAL_EXPIRED');
|
|
73
190
|
if (status === 'applied' && (!this.repositoryAuthority || authority !== this.repositoryAuthority))
|
|
74
191
|
throw new Error('REPOSITORY_AUTHORITY_REQUIRED');
|
|
192
|
+
if (status === 'approved') {
|
|
193
|
+
if (!record.preview_id)
|
|
194
|
+
throw new Error('PREVIEW_REQUIRED');
|
|
195
|
+
await this.getPreview(record.preview_id);
|
|
196
|
+
const current = await this.context();
|
|
197
|
+
if (record.application_id !== current.snapshot.application.application_id || record.environment !== current.snapshot.application.environment)
|
|
198
|
+
throw new Error('PROPOSAL_SCOPE_MISMATCH');
|
|
199
|
+
if (record.base_contract_hash !== current.snapshot.contract_hash || record.base_flow_hash !== await flowSourceHash(current.source))
|
|
200
|
+
throw new Error('STALE_PROPOSAL');
|
|
201
|
+
}
|
|
75
202
|
if (status === 'approved' && record.warnings.some(value => value.startsWith('Authorization ')) && !approveAuthorization)
|
|
76
203
|
throw new Error('AUTHORIZATION_APPROVAL_REQUIRED');
|
|
77
204
|
if (status === 'approved') {
|
package/dist/studio/app.d.ts
CHANGED
|
@@ -9,11 +9,13 @@ export interface StudioAppProps {
|
|
|
9
9
|
namespace?: string;
|
|
10
10
|
deploymentRuntime?: string;
|
|
11
11
|
applicationUrl?: string;
|
|
12
|
+
applicationId?: string;
|
|
13
|
+
environment?: string;
|
|
12
14
|
developmentSession?: Record<string, string>;
|
|
13
15
|
managedPublish?: ManagedPublishConfiguration;
|
|
14
16
|
sourceSync?: SourceSyncConfiguration;
|
|
15
17
|
onConnect?: (url: string, token: string) => void;
|
|
16
18
|
}
|
|
17
|
-
export declare function StudioApp({ db, remoteUrl, token, namespace, deploymentRuntime, applicationUrl, developmentSession, managedPublish, sourceSync, onConnect }: StudioAppProps): React.JSX.Element;
|
|
19
|
+
export declare function StudioApp({ db, remoteUrl, token, namespace, deploymentRuntime, applicationUrl, applicationId, environment, developmentSession, managedPublish, sourceSync, onConnect }: StudioAppProps): React.JSX.Element;
|
|
18
20
|
export default StudioApp;
|
|
19
21
|
//# sourceMappingURL=app.d.ts.map
|
package/dist/studio/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAgBnD,OAA4B,EAAE,KAAK,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AACzG,OAAO,EAAa,KAAK,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAgBnD,OAA4B,EAAE,KAAK,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AACzG,OAAO,EAAa,KAAK,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAMjF,OAAO,EAAgC,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,WAAW,CAAC;AAEnB,MAAM,WAAW,cAAc;IAC7B,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,cAAc,CAAC,EAAE,2BAA2B,CAAC;IAC7C,UAAU,CAAC,EAAE,uBAAuB,CAAC;IACrC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,EAAE,SAAc,EAAE,KAAU,EAAE,SAAqB,EAAE,iBAA6B,EAAE,cAAmB,EAAE,aAAkB,EAAE,WAA0B,EAAE,kBAAkB,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,cAAc,qBAqJjQ;AAED,eAAe,SAAS,CAAC"}
|
|
@@ -13,8 +13,9 @@ export interface SourceSyncConfiguration {
|
|
|
13
13
|
credentialConfigured: boolean;
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
|
-
export declare function AskFeltDB({ configuration, onApplied }: {
|
|
16
|
+
export declare function AskFeltDB({ configuration, onApplied, onProposalCreated }: {
|
|
17
17
|
configuration?: SourceSyncConfiguration;
|
|
18
18
|
onApplied?: () => void;
|
|
19
|
+
onProposalCreated?: (proposalId: string) => void;
|
|
19
20
|
}): React.JSX.Element;
|
|
20
21
|
//# sourceMappingURL=AskFeltDB.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AskFeltDB.d.ts","sourceRoot":"","sources":["../../src/components/AskFeltDB.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,MAAM,WAAW,uBAAuB;IAAG,OAAO,EAAE,OAAO,CAAC;IAAC,aAAa,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,EAAE,cAAc,GAAG,mBAAmB,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,kBAAkB,EAAE,OAAO,CAAC;QAAC,oBAAoB,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE;AAKtS,wBAAgB,SAAS,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,EAAE;IAAE,aAAa,CAAC,EAAE,uBAAuB,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"AskFeltDB.d.ts","sourceRoot":"","sources":["../../src/components/AskFeltDB.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,MAAM,WAAW,uBAAuB;IAAG,OAAO,EAAE,OAAO,CAAC;IAAC,aAAa,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,EAAE,cAAc,GAAG,mBAAmB,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,kBAAkB,EAAE,OAAO,CAAC;QAAC,oBAAoB,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE;AAKtS,wBAAgB,SAAS,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAAE;IAAE,aAAa,CAAC,EAAE,uBAAuB,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAAC,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,qBA4E/L"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { FlowSpec } from '@feltdb/core';
|
|
3
|
+
export declare function ContractInspector({ model, section }: {
|
|
4
|
+
model: FlowSpec | null;
|
|
5
|
+
section: 'schema' | 'policies';
|
|
6
|
+
}): React.JSX.Element;
|
|
7
|
+
//# sourceMappingURL=ContractInspector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContractInspector.d.ts","sourceRoot":"","sources":["../../src/components/ContractInspector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,wBAAgB,iBAAiB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAAE,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,QAAQ,GAAC,UAAU,CAAA;CAAE,qBAM7G"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ManagedInstancePanel.d.ts","sourceRoot":"","sources":["../../src/components/ManagedInstancePanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"ManagedInstancePanel.d.ts","sourceRoot":"","sources":["../../src/components/ManagedInstancePanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAmRxC,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -106,11 +106,7 @@ var i = () => {
|
|
|
106
106
|
if (!u) return;
|
|
107
107
|
let t = e.generateEnvContent({
|
|
108
108
|
url: `https://${i}-feltdb.fly.dev`,
|
|
109
|
-
token: u.secret
|
|
110
|
-
namespace: u.namespace,
|
|
111
|
-
applicationId: i,
|
|
112
|
-
revisionId: "v0.5-alpha",
|
|
113
|
-
environment: "staging"
|
|
109
|
+
token: u.secret
|
|
114
110
|
}), n = new Blob([t], { type: "text/plain" }), r = URL.createObjectURL(n), a = document.createElement("a");
|
|
115
111
|
a.href = r, a.download = ".env.local", document.body.appendChild(a), a.click(), document.body.removeChild(a), URL.revokeObjectURL(r);
|
|
116
112
|
},
|