Skip to content

Commit e5250ee

Browse files
authored
feat: add multi-space session support to SessionConfig (#25)
* feat: add multi-space session support to SessionConfig SessionConfig now accepts optional `additionalSpaces` so a single SIWE signature can cover multiple spaces (e.g., primary + public). The into_message() method generates ReCap capability URIs for all spaces, enabling the SDK to operate on both default and public spaces without requiring a second wallet interaction. * feat: lazy delegation activation - skip missing spaces for multi-space sessions Server now tolerates missing spaces during delegation processing instead of failing with SpaceNotFound. For delegation-only transactions, spaces that don't exist in the DB are skipped (no epoch/event_order created), while the delegation record is still fully saved. Invocations continue to fail explicitly with 404 for non-existent spaces. The /delegate endpoint now returns JSON with activated/skipped space lists, allowing clients to defer public space creation until needed rather than eagerly creating it during signIn.
1 parent b4dc4f8 commit e5250ee

5 files changed

Lines changed: 409 additions & 192 deletions

File tree

.changeset/multi-space-session.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tinycloud-sdk-wasm": minor
3+
---
4+
5+
Add multi-space session support. SessionConfig accepts optional additionalSpaces so a single SIWE signature covers multiple spaces.

src/routes/mod.rs

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use tinycloud_core::{
2020
storage::{ImmutableReadStore, ImmutableStaging},
2121
types::Resource,
2222
util::{DelegationInfo, InvocationInfo},
23-
InvocationOutcome, TxError, TxStoreError,
23+
InvocationOutcome, TransactResult, TxError, TxStoreError,
2424
};
2525

2626
pub mod public;
@@ -79,12 +79,19 @@ pub async fn open_host_key(
7979
})
8080
}
8181

82+
#[derive(Serialize)]
83+
pub struct DelegateResponse {
84+
pub cid: String,
85+
pub activated: Vec<String>,
86+
pub skipped: Vec<String>,
87+
}
88+
8289
#[post("/delegate")]
8390
pub async fn delegate(
8491
d: AuthHeaderGetter<DelegationInfo>,
8592
req_span: TracingSpan,
8693
tinycloud: &State<TinyCloud>,
87-
) -> Result<String, (Status, String)> {
94+
) -> Result<Json<DelegateResponse>, (Status, String)> {
8895
let action_label = "delegation";
8996
let span = info_span!(parent: &req_span.0, "delegate", action = %action_label);
9097
// Instrumenting async block to handle yielding properly
@@ -105,13 +112,37 @@ pub async fn delegate(
105112
e.to_string(),
106113
)
107114
})
108-
.and_then(|c| {
109-
c.into_iter()
115+
.and_then(|result: TransactResult| {
116+
let activated: Vec<String> = result
117+
.commits
118+
.keys()
119+
.map(|s| s.to_string())
120+
.collect();
121+
let skipped: Vec<String> = result
122+
.skipped_spaces
123+
.iter()
124+
.map(|s| s.to_string())
125+
.collect();
126+
127+
// Get CID from the first committed event, or fall back to
128+
// the delegation CID when all spaces were skipped
129+
let cid = result
130+
.commits
131+
.into_values()
110132
.next()
111-
.and_then(|(_, c)| c.committed_events.into_iter().next())
112-
.ok_or_else(|| (Status::Unauthorized, "Delegation not committed".to_string()))
113-
})
114-
.map(|h| h.to_cid(0x55).to_string());
133+
.and_then(|c| c.committed_events.into_iter().next())
134+
.or_else(|| result.delegation_cids.into_iter().next())
135+
.map(|h| h.to_cid(0x55).to_string())
136+
.ok_or_else(|| {
137+
(Status::Unauthorized, "Delegation not committed".to_string())
138+
})?;
139+
140+
Ok(Json(DelegateResponse {
141+
cid,
142+
activated,
143+
skipped,
144+
}))
145+
});
115146
timer.observe_duration();
116147
res
117148
}

0 commit comments

Comments
 (0)