fix(dashboard): F-S-014 warn on any permissiveness increase in topic edit modal
editFlipToExternal warned only on the internal → external transition. Switching `token → public` or `session → public` while already external is equally risky (opens topic to anonymous subscribers) but produced no warning. Replace with editPermissivenessChange that ranks the (external, auth_mode) pair on a 0..3 scale and fires the warning whenever the resulting rank strictly exceeds the current one: 0 internal (any auth) 1 external + session 2 external + token 3 external + public Keep `editFlipToExternal` as an alias pointing at the new derived so nothing downstream breaks. AUDIT.md anchor: F-S-014. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -412,10 +412,24 @@
|
||||
let editTopicAuthMode = $state<TopicAuthMode>('public');
|
||||
let savingTopic = $state(false);
|
||||
let editTopicError = $state<string | null>(null);
|
||||
// Flipping internal → external is the security-sensitive change.
|
||||
const editFlipToExternal = $derived(
|
||||
!!topicToEdit && !topicToEdit.external_subscribable && editTopicExternal
|
||||
);
|
||||
// F-S-014: warn whenever the resulting (external, auth_mode) pair is
|
||||
// strictly more permissive than the current one — not just on the
|
||||
// internal → external flip. The order least → most permissive is:
|
||||
// internal (any auth) < external+session < external+token < external+public
|
||||
const editPermissivenessChange = $derived.by(() => {
|
||||
if (!topicToEdit) return false;
|
||||
const rank = (external: boolean, mode: TopicAuthMode) => {
|
||||
if (!external) return 0;
|
||||
if (mode === 'session') return 1;
|
||||
if (mode === 'token') return 2;
|
||||
return 3; // public
|
||||
};
|
||||
const before = rank(topicToEdit.external_subscribable, topicToEdit.auth_mode);
|
||||
const after = rank(editTopicExternal, editTopicAuthMode);
|
||||
return after > before;
|
||||
});
|
||||
// Kept for narrow callers; semantics now covered by editPermissivenessChange.
|
||||
const editFlipToExternal = $derived(editPermissivenessChange);
|
||||
// Delete confirm.
|
||||
let topicToRemove = $state<Topic | null>(null);
|
||||
let removingTopic = $state(false);
|
||||
|
||||
Reference in New Issue
Block a user