refactor(permissions): preserve pre-PR behavior in three spots
PR #5 review flagged three behavior changes that shouldn't have slipped in. This commit reverts each to match the pre-refactor behavior exactly. 1. User upsert ordering. Split the router hook into two setters: setSenderResolver (runs before agent resolution) and setAccessGate (runs after). Restores the pre-PR sequence where the users row is upserted even if the message is dropped by wiring or trigger rules. 2. dropped_messages audit. Moved src/modules/permissions/db/dropped-messages.ts back to src/db/dropped-messages.ts. The table is core audit infra, not permissions-specific. Router re-writes rows for no_agent_wired and no_trigger_match; the access gate writes rows for policy refusals. 3. Permissionless container fallback. Dropped. poll-loop restores the original deny-all check when NANOCLAW_ADMIN_USER_IDS is empty. Module contract doc updated with the two-hook shape. Validation: host build clean, 137/137 host tests, 17/17 container tests, typecheck clean, service boots to "NanoClaw running" with permissions module registering both hooks and clean SIGTERM shutdown. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
44
src/db/dropped-messages.ts
Normal file
44
src/db/dropped-messages.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { getDb } from './connection.js';
|
||||
|
||||
export interface UnregisteredSender {
|
||||
channel_type: string;
|
||||
platform_id: string;
|
||||
user_id: string | null;
|
||||
sender_name: string | null;
|
||||
reason: string;
|
||||
messaging_group_id: string | null;
|
||||
agent_group_id: string | null;
|
||||
message_count: number;
|
||||
first_seen: string;
|
||||
last_seen: string;
|
||||
}
|
||||
|
||||
export function recordDroppedMessage(msg: {
|
||||
channel_type: string;
|
||||
platform_id: string;
|
||||
user_id: string | null;
|
||||
sender_name: string | null;
|
||||
reason: string;
|
||||
messaging_group_id: string | null;
|
||||
agent_group_id: string | null;
|
||||
}): void {
|
||||
const now = new Date().toISOString();
|
||||
getDb()
|
||||
.prepare(
|
||||
`INSERT INTO unregistered_senders (channel_type, platform_id, user_id, sender_name, reason, messaging_group_id, agent_group_id, message_count, first_seen, last_seen)
|
||||
VALUES (@channel_type, @platform_id, @user_id, @sender_name, @reason, @messaging_group_id, @agent_group_id, 1, @now, @now)
|
||||
ON CONFLICT (channel_type, platform_id) DO UPDATE SET
|
||||
user_id = COALESCE(excluded.user_id, unregistered_senders.user_id),
|
||||
sender_name = COALESCE(excluded.sender_name, unregistered_senders.sender_name),
|
||||
reason = excluded.reason,
|
||||
message_count = unregistered_senders.message_count + 1,
|
||||
last_seen = excluded.last_seen`,
|
||||
)
|
||||
.run({ ...msg, now });
|
||||
}
|
||||
|
||||
export function getUnregisteredSenders(limit = 50): UnregisteredSender[] {
|
||||
return getDb()
|
||||
.prepare('SELECT * FROM unregistered_senders ORDER BY last_seen DESC LIMIT ?')
|
||||
.all(limit) as UnregisteredSender[];
|
||||
}
|
||||
Reference in New Issue
Block a user