Skip to content

Commit 26f562a

Browse files
Added security note for scheduled tables and added missing sender_auth to ReducerContext doc
1 parent ccd71a9 commit 26f562a

2 files changed

Lines changed: 55 additions & 3 deletions

File tree

docs/docs/00400-tables/00500-scheduled-tables.md

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public static void SendReminder(ReducerContext ctx, Reminder reminder)
5959
<TabItem value="typescript" label="TypeScript">
6060

6161
```typescript
62-
const Reminder = table(
62+
const reminder = table(
6363
{ name: 'reminder', scheduled: 'send_reminder' },
6464
{
6565
scheduled_id: t.u64().primaryKey().autoInc(),
@@ -68,7 +68,7 @@ const Reminder = table(
6868
}
6969
);
7070

71-
spacetimedb.reducer('send_reminder', { arg: Reminder.rowType }, (_ctx, { arg }) => {
71+
spacetimedb.reducer('send_reminder', { arg: reminder.rowType }, (_ctx, { arg }) => {
7272
// Invoked automatically by the scheduler
7373
// arg.message, arg.scheduled_at, arg.scheduled_id
7474
});
@@ -84,6 +84,56 @@ spacetimedb.reducer('send_reminder', { arg: Reminder.rowType }, (_ctx, { arg })
8484
3. **When the time arrives**, the specified reducer/procedure is automatically called with the row as a parameter
8585
4. **The row is typically deleted** or updated by the reducer after processing
8686

87+
## Security Considerations
88+
89+
:::warning Scheduled Reducers Are Callable by Clients
90+
Scheduled reducers are normal reducers that can also be invoked by external clients. If a scheduled reducer should only execute via the scheduler, add authentication checks.
91+
:::
92+
93+
<Tabs groupId="server-language" queryString>
94+
<TabItem value="rust" label="Rust">
95+
96+
```rust
97+
#[spacetimedb::reducer]
98+
fn send_reminder(ctx: &ReducerContext, reminder: Reminder) -> Result<(), String> {
99+
if !ctx.sender_auth().is_internal() {
100+
return Err("This reducer can only be called by the scheduler".to_string());
101+
}
102+
// Process the scheduled reminder
103+
Ok(())
104+
}
105+
```
106+
107+
</TabItem>
108+
<TabItem value="csharp" label="C#">
109+
110+
```csharp
111+
[SpacetimeDB.Reducer()]
112+
public static void SendReminder(ReducerContext ctx, Reminder reminder)
113+
{
114+
if (!ctx.SenderAuth.IsInternal)
115+
{
116+
throw new Exception("This reducer can only be called by the scheduler");
117+
}
118+
// Process the scheduled reminder
119+
}
120+
```
121+
122+
</TabItem>
123+
<TabItem value="typescript" label="TypeScript">
124+
125+
```typescript
126+
spacetimedb.reducer('send_reminder', { arg: Reminder.rowType }, (ctx, { arg }) => {
127+
if (!ctx.senderAuth.isInternal) {
128+
throw new SenderError('This reducer can only be called by the scheduler');
129+
}
130+
// Process the scheduled reminder
131+
});
132+
```
133+
134+
</TabItem>
135+
</Tabs>
136+
87137
## Use Cases
88138

89139
- **Reminders and notifications** - Schedule messages to be sent at specific times

docs/docs/00500-functions/00200-reducers/00300-reducer-context.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,14 +319,15 @@ spacetimedb.reducer('send_reminder', { arg: scheduledTask.rowType }, (ctx, { arg
319319
- `identity() -> Identity` - Get the module's identity
320320
- `rng() -> &StdbRng` - Get the random number generator
321321
- `random<T>() -> T` - Generate a single random value
322-
- `sender_auth() -> &AuthCtx` - Get authorization context for the caller
322+
- `sender_auth() -> &AuthCtx` - Get authorization context for the caller (includes JWT claims and internal call detection)
323323
</TabItem>
324324
<TabItem value="csharp" label="C#">
325325

326326
| Property | Type | Description |
327327
| -------------- | --------------------- | ----------------------------------------------- |
328328
| `Db` | `DbView` | Access to the module's database tables |
329329
| `Sender` | `Identity` | Identity of the caller |
330+
| `SenderAuth` | `AuthCtx` | Authorization context for the caller (includes JWT claims and internal call detection) |
330331
| `ConnectionId` | `ConnectionId?` | Connection ID of the caller, if available |
331332
| `Timestamp` | `Timestamp` | Time when the reducer was invoked |
332333
| `Rng` | `Random` | Random number generator |
@@ -338,6 +339,7 @@ spacetimedb.reducer('send_reminder', { arg: scheduledTask.rowType }, (ctx, { arg
338339
| -------------- | -------------------------- | ----------------------------------------------- |
339340
| `db` | `DbView` | Access to the module's database tables |
340341
| `sender` | `Identity` | Identity of the caller |
342+
| `senderAuth` | `AuthCtx` | Authorization context for the caller (includes JWT claims and internal call detection) |
341343
| `connectionId` | `ConnectionId \| undefined`| Connection ID of the caller, if available |
342344
| `timestamp` | `Timestamp` | Time when the reducer was invoked |
343345

0 commit comments

Comments
 (0)