You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: document security block config options and injection mechanism
Expand documentation for disable_policy, disable_suffix, and
strict_policy across config.example.toml, SecurityConfig doc comments,
and the RFC. Clarifies the two-layer security model, how disabling
each layer works independently, and warns about disabling both.
Updates RFC to reflect concatenation into last message (not separate
user message).
Copy file name to clipboardExpand all lines: docs/RFC-LocalGPT-Security-Policy.md
+42-20Lines changed: 42 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -435,15 +435,29 @@ The security block is **injected on every API call**, not stored in conversation
435
435
436
436
**Message array structure per API call:**
437
437
438
+
The security block is **concatenated into the last user or tool-result message** (separated by `\n\n`) rather than appended as a separate user message. This avoids consecutive same-role messages, which violates the Anthropic Messages API protocol.
If the last message is neither User nor Tool (edge case: Assistant or System), the security block falls back to a separate User message.
448
+
445
449
The security block is a synthetic injection. It is not persisted in `session.rs` conversation history, not included in session compaction/summarization, and not visible to the user.
446
450
451
+
Both layers can be independently disabled via `config.toml`:
452
+
453
+
```toml
454
+
[security]
455
+
disable_policy = true# skip LocalGPT.md content
456
+
disable_suffix = true# skip hardcoded reminder
457
+
```
458
+
459
+
When both are disabled, `build_ending_security_block()` returns an empty string and no injection occurs.
460
+
447
461
**Token budget:** Hardcoded suffix ≈80 tokens (always included, non-negotiable). User policy ≤1000 tokens. Total ≈1080 tokens per turn. Over a 30-turn session this consumes ~32K tokens — about 27% of `reserve_tokens` (8000) should be allocated for the security block to prevent it from being dropped during context window management.
448
462
449
463
**Reserve token accounting:** Update `reserve_tokens` calculation in `session.rs` to include `SECURITY_BLOCK_RESERVE`:
@@ -514,32 +528,40 @@ self.verified_security_policy = match &policy {
514
528
};
515
529
```
516
530
517
-
**At every API call** (`build_messages_for_api_call()`) — inject fresh:
531
+
**At every API call** (`messages_for_api_call()`) — inject fresh:
// Concatenate into the last User or Tool message to avoid
548
+
// consecutive same-role messages (Anthropic API requirement).
549
+
ifletSome(last) =messages.last_mut()
550
+
&&matches!(last.role, Role::User|Role::Tool)
551
+
{
552
+
last.content.push_str("\n\n");
553
+
last.content.push_str(&security_block);
554
+
} else {
555
+
// Fallback: no messages or last message is Assistant/System
556
+
messages.push(Message::user(&security_block));
557
+
}
529
558
}
530
559
531
-
// Security block (recency position — always last before generation)
532
-
// Appended to the last user message or as a trailing user message
533
-
letsecurity=build_ending_security_block(
534
-
self.verified_security_policy.as_deref(),
535
-
);
536
-
messages.push(Message::user(&security));
537
-
538
560
messages
539
561
}
540
562
```
541
563
542
-
**Note:** The security block is injected as a `user`-role message (or appended to the final user message content) because some providers do not support interleaved `system` messages, and user-role content at the end receives strong recency attention regardless of role.
564
+
**Note:** The security block is concatenated into the last user/tool message content rather than appended as a separate user message. This avoids consecutive same-role messages (which violates the Anthropic Messages API protocol) while keeping the security text in the recency position.
0 commit comments