@feltdb/core 0.7.4 → 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 (127) hide show
  1. package/README.md +25 -0
  2. package/dist/application-development.d.ts +10 -3
  3. package/dist/application-development.d.ts.map +1 -1
  4. package/dist/application-development.js +11 -1
  5. package/dist/application-manifest.d.ts +2 -0
  6. package/dist/application-manifest.d.ts.map +1 -1
  7. package/dist/application-manifest.js +1 -1
  8. package/dist/application-understanding.d.ts +76 -0
  9. package/dist/application-understanding.d.ts.map +1 -0
  10. package/dist/application-understanding.js +282 -0
  11. package/dist/canonical-application.d.ts +1 -0
  12. package/dist/canonical-application.d.ts.map +1 -1
  13. package/dist/canonical-application.js +3 -2
  14. package/dist/cli/ai-model-config.js +3 -3
  15. package/dist/cli/cli.js +1 -1
  16. package/dist/cli/commands.js +321 -45
  17. package/dist/cli/index.js +1 -1
  18. package/dist/cli/managed-environment.js +6 -0
  19. package/dist/cli/managed-project.js +6 -0
  20. package/dist/cli/proposal-client.js +16 -3
  21. package/dist/cli/publish-engine.js +8 -5
  22. package/dist/cli/repository-evidence.js +55 -0
  23. package/dist/cli/source-sync.js +220 -61
  24. package/dist/convergence.d.ts +55 -0
  25. package/dist/convergence.d.ts.map +1 -0
  26. package/dist/convergence.js +63 -0
  27. package/dist/create/cli.js +10 -1
  28. package/dist/create/create.js +10 -12
  29. package/dist/create/managed-account.js +72 -7
  30. package/dist/create/package-versions.js +1 -1
  31. package/dist/create/server-source/crates/feltdb/src/application.rs +14 -0
  32. package/dist/create/server-source/crates/feltdb/src/lib.rs +20 -2
  33. package/dist/create/server-source/crates/feltdb-server/src/app_state.rs +12 -24
  34. package/dist/create/server-source/crates/feltdb-server/src/application_contract.rs +11 -3
  35. package/dist/create/server-source/crates/feltdb-server/src/authenticated_principal.rs +0 -1
  36. package/dist/create/server-source/crates/feltdb-server/src/certification_harness.rs +23 -22
  37. package/dist/create/server-source/crates/feltdb-server/src/connections.rs +14 -0
  38. package/dist/create/server-source/crates/feltdb-server/src/delegation_token.rs +5 -15
  39. package/dist/create/server-source/crates/feltdb-server/src/durable_operations.rs +13 -28
  40. package/dist/create/server-source/crates/feltdb-server/src/identity.rs +79 -14
  41. package/dist/create/server-source/crates/feltdb-server/src/key_management.rs +28 -7
  42. package/dist/create/server-source/crates/feltdb-server/src/lib.rs +5 -5
  43. package/dist/create/server-source/crates/feltdb-server/src/main.rs +1929 -261
  44. package/dist/create/server-source/crates/feltdb-server/src/managed_diagnostics.rs +10 -30
  45. package/dist/create/server-source/crates/feltdb-server/src/membership_policy.rs +12 -4
  46. package/dist/create/server-source/crates/feltdb-server/src/request_telemetry.rs +8 -6
  47. package/dist/create/server-source/crates/feltdb-server/src/snapshot_cursor.rs +10 -14
  48. package/dist/create/server-source/crates/feltdb-server/src/tenancy.rs +191 -22
  49. package/dist/create/server-source/crates/feltdb-server/src/tenant_policies.rs +9 -21
  50. package/dist/create/server-source/crates/feltdb-server/src/transaction_idempotency.rs +5 -3
  51. package/dist/create/server-source/crates/feltdb-server/src/transaction_recovery.rs +9 -8
  52. package/dist/create/server-source/crates/feltdb-server/tests/revision_recovery_integration_test.rs +1 -4
  53. package/dist/create/template/default-project/feltdb.flow +5 -0
  54. package/dist/create/template/default-project/src/context/AuthContext.tsx +9 -1
  55. package/dist/create/template/default-project/src/pages/SignUp.tsx +1 -1
  56. package/dist/flowspec.d.ts +1 -0
  57. package/dist/flowspec.d.ts.map +1 -1
  58. package/dist/flowspec.js +51 -12
  59. package/dist/http-client.d.ts +166 -14
  60. package/dist/http-client.d.ts.map +1 -1
  61. package/dist/http-client.js +91 -31
  62. package/dist/http-db.d.ts +3 -0
  63. package/dist/http-db.d.ts.map +1 -1
  64. package/dist/http-db.js +28 -3
  65. package/dist/index-core.d.ts +5 -0
  66. package/dist/index-core.d.ts.map +1 -1
  67. package/dist/index-core.js +5 -0
  68. package/dist/intent.d.ts +98 -0
  69. package/dist/intent.d.ts.map +1 -0
  70. package/dist/intent.js +343 -0
  71. package/dist/module-intent.d.ts +51 -0
  72. package/dist/module-intent.d.ts.map +1 -0
  73. package/dist/module-intent.js +230 -0
  74. package/dist/module.d.ts +105 -0
  75. package/dist/module.d.ts.map +1 -0
  76. package/dist/module.js +566 -0
  77. package/dist/proposal.d.ts +92 -4
  78. package/dist/proposal.d.ts.map +1 -1
  79. package/dist/proposal.js +150 -6
  80. package/dist/studio/app.d.ts +3 -1
  81. package/dist/studio/app.d.ts.map +1 -1
  82. package/dist/studio/components/AskFeltDB.d.ts +2 -1
  83. package/dist/studio/components/AskFeltDB.d.ts.map +1 -1
  84. package/dist/studio/components/ContractInspector.d.ts +7 -0
  85. package/dist/studio/components/ContractInspector.d.ts.map +1 -0
  86. package/dist/studio/components/ManagedInstancePanel.d.ts.map +1 -1
  87. package/dist/studio/components/ManagedInstancePanel.js +1 -5
  88. package/dist/studio/components/ModuleExplorer.d.ts +6 -0
  89. package/dist/studio/components/ModuleExplorer.d.ts.map +1 -0
  90. package/dist/studio/components/ProposalBrowser.d.ts +10 -1
  91. package/dist/studio/components/ProposalBrowser.d.ts.map +1 -1
  92. package/dist/studio/components/StateExplorer.d.ts +6 -7
  93. package/dist/studio/components/StateExplorer.d.ts.map +1 -1
  94. package/dist/studio/components/index.d.ts +2 -0
  95. package/dist/studio/components/index.d.ts.map +1 -1
  96. package/dist/studio/components/index.js +4 -4
  97. package/dist/studio/components-Duq2xQWt.js +2845 -0
  98. package/dist/studio/index.js +193 -147
  99. package/dist/studio/studio.css +1 -1
  100. package/dist/studio/utils/index.d.ts +2 -0
  101. package/dist/studio/utils/index.d.ts.map +1 -1
  102. package/dist/studio/utils/index.js +14 -12
  103. package/dist/studio/utils/managed-instance.d.ts +0 -4
  104. package/dist/studio/utils/managed-instance.d.ts.map +1 -1
  105. package/dist/studio/utils/managed-instance.js +0 -4
  106. package/dist/studio/utils/proposal-api.d.ts +56 -0
  107. package/dist/studio/utils/proposal-api.d.ts.map +1 -0
  108. package/dist/studio/utils/proposal-api.js +94 -0
  109. package/dist/studio/utils/service-api.d.ts +81 -0
  110. package/dist/studio/utils/service-api.d.ts.map +1 -0
  111. package/dist/studio/utils/service-api.js +51 -0
  112. package/dist/studio-app/assets/{feltdb_wasm-B-Ccgccb.js → feltdb_wasm-bIqcRzAr.js} +1 -1
  113. package/dist/studio-app/assets/feltdb_wasm_bg-BE79okwX.wasm +0 -0
  114. package/dist/studio-app/assets/{index-BRrmvaKw.css → index-Cd_NPw14.css} +1 -1
  115. package/dist/studio-app/assets/index-XGYdlElN.js +29 -0
  116. package/dist/studio-app/index.html +2 -2
  117. package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
  118. package/dist/workspace/local-development-authority.d.ts +2 -0
  119. package/dist/workspace/local-development-authority.d.ts.map +1 -1
  120. package/dist/workspace/local-development-authority.js +128 -4
  121. package/package.json +1 -1
  122. package/dist/studio/components-Bm4sjhcX.js +0 -2162
  123. package/dist/studio-app/assets/dist-DA1MYSzp.js +0 -1
  124. package/dist/studio-app/assets/feltdb_wasm_bg-wH3enJIA.wasm +0 -0
  125. package/dist/studio-app/assets/index-CEIqowCh.js +0 -42
  126. package/dist/studio-app/assets/lib-B2_7fcn7.js +0 -69
  127. package/dist/studio-app/assets/worker-CARZ5g7K.js +0 -69
@@ -137,35 +137,93 @@ impl IdentityStore {
137
137
  .identities
138
138
  .clone())
139
139
  }
140
- pub fn sign_up(&self, email: &str, password: &str, display_name: Option<String>) -> Result<(Identity, IdentitySession, String), String> {
140
+ pub fn sign_up(
141
+ &self,
142
+ email: &str,
143
+ password: &str,
144
+ display_name: Option<String>,
145
+ ) -> Result<(Identity, IdentitySession, String), String> {
141
146
  let normalized = email.trim().to_lowercase();
142
- if normalized.is_empty() || password.len() < 8 { return Err("email and a password of at least 8 characters are required".into()); }
143
- if self.state.read().map_err(|_| "identity lock poisoned")?.identities.iter().any(|value| value.email.as_deref() == Some(&normalized)) {
147
+ if normalized.is_empty() || password.len() < 8 {
148
+ return Err("email and a password of at least 8 characters are required".into());
149
+ }
150
+ if self
151
+ .state
152
+ .read()
153
+ .map_err(|_| "identity lock poisoned")?
154
+ .identities
155
+ .iter()
156
+ .any(|value| value.email.as_deref() == Some(&normalized))
157
+ {
144
158
  return Err("identity already exists".into());
145
159
  }
146
- let mut identity = self.normalize("password", &normalized, Some(normalized.clone()), display_name, serde_json::json!({}))?;
160
+ let mut identity = self.normalize(
161
+ "password",
162
+ &normalized,
163
+ Some(normalized.clone()),
164
+ display_name,
165
+ serde_json::json!({}),
166
+ )?;
147
167
  identity.status = IdentityStatus::Active;
148
168
  let mut state = self.state.write().map_err(|_| "identity lock poisoned")?;
149
- if let Some(stored) = state.identities.iter_mut().find(|value| value.identity_id == identity.identity_id) { stored.status = IdentityStatus::Active; }
150
- state.password_hashes.insert(identity.subject_id.clone(), Self::hash_password(password)?);
169
+ if let Some(stored) = state
170
+ .identities
171
+ .iter_mut()
172
+ .find(|value| value.identity_id == identity.identity_id)
173
+ {
174
+ stored.status = IdentityStatus::Active;
175
+ }
176
+ state
177
+ .password_hashes
178
+ .insert(identity.subject_id.clone(), Self::hash_password(password)?);
151
179
  self.persist(&state)?;
152
180
  drop(state);
153
181
  let (session, token) = self.issue_session(&identity, "password", None, 15 * 60)?;
154
182
  Ok((identity, session, token))
155
183
  }
156
- pub fn sign_in(&self, email: &str, password: &str) -> Result<(Identity, IdentitySession, String), String> {
184
+ pub fn sign_in(
185
+ &self,
186
+ email: &str,
187
+ password: &str,
188
+ ) -> Result<(Identity, IdentitySession, String), String> {
157
189
  let normalized = email.trim().to_lowercase();
158
190
  let state = self.state.read().map_err(|_| "identity lock poisoned")?;
159
- let identity = state.identities.iter().find(|value| value.email.as_deref() == Some(&normalized) && value.status == IdentityStatus::Active).cloned().ok_or("invalid credentials")?;
160
- let valid = state.password_hashes.get(&identity.subject_id).is_some_and(|hash| Self::verify_password(hash, password));
191
+ let identity = state
192
+ .identities
193
+ .iter()
194
+ .find(|value| {
195
+ value.email.as_deref() == Some(&normalized)
196
+ && value.status == IdentityStatus::Active
197
+ })
198
+ .cloned()
199
+ .ok_or("invalid credentials")?;
200
+ let valid = state
201
+ .password_hashes
202
+ .get(&identity.subject_id)
203
+ .is_some_and(|hash| Self::verify_password(hash, password));
161
204
  drop(state);
162
- if !valid { return Err("invalid credentials".into()); }
205
+ if !valid {
206
+ return Err("invalid credentials".into());
207
+ }
163
208
  let (session, token) = self.issue_session(&identity, "password", None, 15 * 60)?;
164
209
  Ok((identity, session, token))
165
210
  }
166
211
  pub fn authenticate_session(&self, token: &str) -> Option<IdentitySession> {
167
212
  let current = now();
168
- self.state.read().ok()?.sessions.iter().find(|value| value.refresh_hash.as_deref().is_some_and(|hash| Self::verify_password(hash, token)) && value.status == "active" && value.expires_at > current).cloned()
213
+ self.state
214
+ .read()
215
+ .ok()?
216
+ .sessions
217
+ .iter()
218
+ .find(|value| {
219
+ value
220
+ .refresh_hash
221
+ .as_deref()
222
+ .is_some_and(|hash| Self::verify_password(hash, token))
223
+ && value.status == "active"
224
+ && value.expires_at > current
225
+ })
226
+ .cloned()
169
227
  }
170
228
  pub fn sessions(&self, subject: &str) -> Result<Vec<IdentitySession>, String> {
171
229
  Ok(self
@@ -282,11 +340,18 @@ mod tests {
282
340
  fn actor_tokens_are_short_lived_hashed_and_revocable() {
283
341
  let p = std::env::temp_dir().join(format!("identity-session-{}.json", id("test")));
284
342
  let store = IdentityStore::load(&p).unwrap();
285
- let (identity, session, token) = store.sign_up("actor@example.com", "correct horse", Some("Actor".into())).unwrap();
343
+ let (identity, session, token) = store
344
+ .sign_up("actor@example.com", "correct horse", Some("Actor".into()))
345
+ .unwrap();
286
346
  assert!(session.expires_at - session.issued_at <= 15 * 60);
287
347
  assert_ne!(session.refresh_hash.as_deref(), Some(token.as_str()));
288
- assert_eq!(store.authenticate_session(&token).unwrap().subject_id, identity.subject_id);
289
- store.revoke_session(&identity.subject_id, &session.session_id, "test").unwrap();
348
+ assert_eq!(
349
+ store.authenticate_session(&token).unwrap().subject_id,
350
+ identity.subject_id
351
+ );
352
+ store
353
+ .revoke_session(&identity.subject_id, &session.session_id, "test")
354
+ .unwrap();
290
355
  assert!(store.authenticate_session(&token).is_none());
291
356
  let _ = std::fs::remove_file(p);
292
357
  }
@@ -1,12 +1,15 @@
1
1
  use axum::{
2
- extract::{Path, State},
2
+ extract::{Extension, Path, State},
3
3
  http::StatusCode,
4
4
  Json,
5
5
  };
6
6
  use serde::{Deserialize, Serialize};
7
7
  use std::time::{SystemTime, UNIX_EPOCH};
8
8
 
9
- use crate::{auth::ApiKeySummary, app_state::AppState};
9
+ use crate::{
10
+ app_state::AppState,
11
+ auth::{ApiKeySummary, Principal},
12
+ };
10
13
 
11
14
  #[derive(Debug, Serialize)]
12
15
  pub struct KeyListResponse {
@@ -18,6 +21,7 @@ pub struct CreateKeyRequest {
18
21
  pub id: Option<String>,
19
22
  pub namespace: String,
20
23
  pub scopes: Vec<String>,
24
+ pub application_id: Option<String>,
21
25
  }
22
26
 
23
27
  #[derive(Debug, Serialize)]
@@ -38,6 +42,7 @@ pub async fn list_keys(
38
42
 
39
43
  pub async fn create_key(
40
44
  State(state): State<AppState>,
45
+ Extension(principal): Extension<Principal>,
41
46
  Json(req): Json<CreateKeyRequest>,
42
47
  ) -> Result<(StatusCode, Json<CreateKeyResponse>), (StatusCode, String)> {
43
48
  let timestamp = SystemTime::now()
@@ -46,15 +51,31 @@ pub async fn create_key(
46
51
  .as_secs();
47
52
 
48
53
  let name = req.id.unwrap_or_else(|| format!("key-{}", timestamp));
54
+ let scopes = req.scopes;
55
+ let mut authentication_namespaces = vec![req.namespace];
56
+ if !authentication_namespaces
57
+ .iter()
58
+ .any(|value| value == state.namespace.as_ref())
59
+ {
60
+ authentication_namespaces.push(state.namespace.to_string());
61
+ }
49
62
  let key = state
50
63
  .keys
51
- .create(
52
- name,
53
- req.scopes,
54
- vec![req.namespace],
55
- )
64
+ .create(name, scopes.clone(), authentication_namespaces)
56
65
  .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e))?;
57
66
 
67
+ if let Some(application_id) = req.application_id {
68
+ if let Err(error) = state.tenancy.register_application_service(
69
+ &principal.key_id,
70
+ &key.id,
71
+ &application_id,
72
+ scopes,
73
+ ) {
74
+ let _ = state.keys.revoke(&key.id);
75
+ return Err((StatusCode::FORBIDDEN, error));
76
+ }
77
+ }
78
+
58
79
  Ok((
59
80
  StatusCode::CREATED,
60
81
  Json(CreateKeyResponse {
@@ -6,17 +6,17 @@ pub mod auth;
6
6
  pub mod authenticated_principal;
7
7
  pub mod authorization;
8
8
  pub mod backup;
9
- pub mod certification_harness;
10
- pub mod delegation_token;
11
- pub mod durable_operations;
12
- pub mod key_management;
13
9
  pub mod causal;
14
10
  pub mod certification;
11
+ pub mod certification_harness;
15
12
  pub mod clock;
16
13
  pub mod cluster;
17
14
  pub mod connections;
18
15
  pub mod content;
16
+ pub mod delegation_token;
17
+ pub mod durable_operations;
19
18
  pub mod identity;
19
+ pub mod key_management;
20
20
  pub mod key_provider;
21
21
  pub mod leases;
22
22
  pub mod managed_diagnostics;
@@ -29,8 +29,8 @@ pub mod releases;
29
29
  pub mod request_telemetry;
30
30
  pub mod sessions;
31
31
  pub mod snapshot_cursor;
32
- pub mod tenant_policies;
33
32
  pub mod tenancy;
33
+ pub mod tenant_policies;
34
34
  pub mod transaction_idempotency;
35
35
  pub mod transaction_recovery;
36
36
  pub mod versions;