Skip to content

feat: RBAC + ABAC permission system for multi-agent multi-user#67

Merged
vaayne merged 53 commits intomainfrom
feat/rbac
Mar 21, 2026
Merged

feat: RBAC + ABAC permission system for multi-agent multi-user#67
vaayne merged 53 commits intomainfrom
feat/rbac

Conversation

@vaayne
Copy link
Owner

@vaayne vaayne commented Mar 20, 2026

Summary

Full RBAC + ABAC permission system for anna with unified user management and per-user data isolation.

Key changes

  • Single unified user table: auth_users is the only user table (settings_users eliminated). Channel identities linked via auth_identities.
  • RBAC + ABAC policy engine: Role system (admin, user) with attribute-based policies. Deny-overrides evaluation. 9 built-in system policies.
  • Admin UI authentication: Username/password login, session-based auth, rate limiting, CORS hardening.
  • Agent scoping: System-scope (all users) vs restricted (assigned users only). Policy engine enforcement at API and channel level.
  • Per-user data isolation: Per-user workspace directories, per-user skill installation, file tool sandbox, per-user session/memory scoping.
  • Channel identity linking: /link <code> command flow — generate code in admin profile, send to bot.
  • Scheduler RBAC: Users see/manage only their own jobs. System jobs (user_id=0) broadcast to all. User jobs notify only the owner via linked identities.
  • Session RBAC: Non-admin users see only their own sessions.
  • Per-user notifications: Dispatcher.NotifyUser resolves channel identities to target specific users.
  • Admin user management: Roles, agent assignment, identity unlink, activation/deactivation, default agent, memory per user.

DB changes

  • auth_users now includes default_agent_id (absorbed from dropped settings_users)
  • settings_users table dropped
  • 7 auth tables: auth_users, auth_roles, auth_user_roles, auth_identities, auth_policies, auth_user_agents, auth_sessions
  • settings_agents.scope column added
  • ctx_agent_memory.user_id FK dropped (supports both legacy and auth user IDs)
  • 3 migrations: add-auth-tables, fix_memory_user_fk, consolidate_users

Architecture

  • internal/auth/ — Types, policy engine, password, sessions, rate limiter, sandbox, link codes, seed
  • internal/db/authstore.go — SQLite AuthStore implementation
  • internal/channel/identity.go — Single ResolveUser path via auth_identities
  • internal/channel/resolved.goResolvedChat with single auth.AuthUser (no dual ID)
  • internal/channel/notifier.goNotifyUser for per-user notification routing

Test plan

  • All tests pass with -race flag
  • 0 lint issues
  • Register first user (gets admin), register second (gets user role)
  • Login/logout, session expiry
  • Link QQ/Telegram identity via /link <code> flow
  • Unlink identity from admin panel, re-link to different user
  • Scheduler RBAC: user jobs visible only to owner
  • Session RBAC: non-admin sees only own sessions
  • Per-user notification routing via linked identities
  • Create restricted agent, assign user, verify access enforcement
  • Install skill as user A, verify user B doesn't see it

vaayne added 30 commits March 20, 2026 18:41
Add 7 new auth tables (auth_users, auth_roles, auth_user_roles,
auth_identities, auth_policies, auth_user_agents, auth_sessions) and
scope column to settings_agents. Generate Atlas migration.
Add query files for auth_users, auth_roles, auth_user_roles,
auth_identities, auth_policies, auth_user_agents, auth_sessions.
Regenerate sqlc to include new auth types and updated settings_agents.
…e, and DB implementation

- types.go: AuthUser, Role, Policy, AccessRequest, Subject, Resource, Action, Identity, Session
- password.go: bcrypt hash/verify with cost=12
- store.go: AuthStore interface (separate from config.Store)
- authdb/store.go: SQLite implementation using sqlc queries
- password_test.go: hash, verify, wrong password, empty hash
- authdb/store_test.go: CRUD for users, roles, identities, policies,
  user-agent assignments, sessions; cascade delete; interface check
- Change UpdateSessionExpiry to accept time.Time instead of string
- Wrap all error returns with fmt.Errorf context
- Log parseTime failures instead of silently discarding
Implements the ABAC policy evaluation engine for Phase 2:
- PolicyEngine loads enabled policies sorted by priority
- Can/Must methods evaluate access requests
- Deny-overrides algorithm: any deny wins, at least one allow needed
- Condition evaluator supports eq, neq, in, not_in, contains operators
- Attribute references (subject.id, resource.owner_id, etc.)
Seeds 2 system roles (admin, user) and 8 built-in ABAC policies
on bootstrap. Uses idempotent pattern — existing entries are skipped.
Calls auth.SeedRolesAndPolicies after DB migrations and config seed,
ensuring built-in roles and policies exist on every startup.
Tests cover:
- Condition evaluation (eq, neq, in, not_in, contains, attr refs, AND logic)
- Policy matching (roles, actions, resources, wildcards, invalid JSON)
- Deny-overrides (deny wins, default deny, allow when matched)
- Built-in policy scenarios (admin full access, user own data, etc.)
- Seed idempotency (run twice without error)
- Engine creation from seeded DB
- session.go: crypto/rand session IDs (32 bytes hex), cookie helpers
  (HttpOnly, SameSite=Lax, Secure flag, 7-day MaxAge)
- ratelimit.go: in-memory rate limiter with per-IP (10 req/min) and
  per-username (5 failures -> 30s cooldown) throttling via sync.Map
- Tests for both packages with -race
- login.templ: login form with register toggle, daisyUI styled
- login.js: Alpine.js component for login/register API calls
- loginlayout.templ: standalone layout without navbar for login page
- auth.go: register, login, logout, me API handlers
- middleware.go: session-based auth middleware + admin-only guard
- server.go: CORS hardening (configurable origin, credentials),
  auth middleware on all routes, admin-only route guards, role-based
  root redirect (unauth->login, user->agents, admin->providers)
- navbar.templ: role-based nav items, username + logout button
- layout.templ: pass username/isAdmin to navbar
- render.go: extract auth info from context for page rendering
- Updated callers in cmd/anna (gateway.go, onboard.go) to pass
  AuthStore and PolicyEngine to admin.New()
- auth_test.go: register, login, logout, /me, password validation,
  duplicate username, wrong password, first-user admin role, expired
  session denial
- server_test.go: updated for auth-aware server (session cookies,
  admin/non-admin access control, unauthenticated redirects)
- Separate CheckIP from RecordIPAttempt (no counter on check)
- Add rate limiting to register endpoint
- Add username (max 64) and password (max 72) length limits
- Fix first-user race: check count before creating user
- Make agent CRUD (POST/PUT/DELETE) admin-only
- Cache CORS origin at startup instead of per-request DB query
- Set Secure=true on ClearSessionCookie for HTTPS compat
…link code store

- Create internal/auth/linkcode.go: in-memory LinkCodeStore with sync.Map, 5-min TTL
- Create profile templ page with password change form, linked identities list, and link code generation
- Create profile.js Alpine component with full CRUD for identities and password
- Create profile API handlers: list/unlink identities, change password, generate link code
- Add /profile page route, profile API routes, and LinkCodes accessor on Server
- Make username in navbar a clickable link to /profile
- Create internal/channel/linkcode.go: shared TryLinkCode function
- Add WithAuth option to telegram, qq, feishu bots
- Intercept 6-char alphanumeric codes in text handlers before command processing
- Create auth_identity on valid code, reply with success/error message
- Platform mismatch detection (code for telegram sent to qq, etc.)
- Add ResolvedIdentity type with AuthUserID and Roles fields
- Add ResolveUserWithAuth: auth_identities lookup -> auto-migrate from settings_users
- Add ResolveWithAuth for auth-aware full resolution path
- Auto-migration: creates auth_user + auth_identity for unlinked settings_users
- Channel bots use ResolveWithAuth when authStore is configured
- Backward compatible: falls back to legacy Resolve when auth not configured
…entity resolution

- LinkCodeStore tests: generate, consume, single-use, case-insensitive, uniqueness, IsLinkCode
- Profile API tests: list identities, change password, generate link code, unlink identity, ownership check
- Identity resolution tests: auto-migration, linked identity lookup, idempotency
- TryLinkCode tests: success, wrong platform, invalid code, non-code text
- All tests pass with -race
Add AgentScopeSystem and AgentScopeRestricted constants. Map scope
column in agentFromDB, CreateAgent, UpdateAgent, and SeedDefaults.
Update sqlc queries to include scope in INSERT and UPDATE.
- Add GET/POST/DELETE /api/agents/{id}/users endpoints (admin-only)
- Add scope dropdown and user assignment modal to agents page
- Filter agent list/get by policy engine for non-admin users
- Non-admin users see only system-scoped + assigned agents
- Tests for scope CRUD, user assignment, and access filtering
- Add ResolveAgentWithAuth with policy engine access checks
- Return ErrAgentAccessDenied when user cannot access an agent
- Filter fallback agent list by accessible agents
- Add engine field to Telegram/QQ/Feishu bots via WithAuth option
- Update ResolveWithAuth to pass engine through to agent resolution
- Tests for system/restricted/admin/fallback/group-chat scenarios
…eway

Move auth store and policy engine creation before bot initialization so
all channel bots get WithAuth with auth store, engine, and link codes.
This enables agent access enforcement on all channel messages.
- Add SetupUserWorkspace() for per-user dirs under workspaces/{agentID}/users/{userID}/
- Add UserSkillsDir/UserDataDir helpers
- Modify SkillsTool to accept userID; per-user skills path when userID > 0
- Update install/list/load/remove to use per-user skillsDir()
- Update LoadSkills priority chain: project > user > agent > common > builtin
- Add UserSkillsDir field to DBPromptParams for prompt building
- Comprehensive tests for workspace isolation and per-user skills
- Add UserID to RunnerParams, pass through pool -> factory
- Create per-user workspace and tools in factory when UserID > 0
- Add UserDataDir to GoRunnerConfig for sandbox-aware tool registry
- Add auth.ValidatePath() with symlink resolution for path sandbox
- Add sandboxTool wrapper for read/write/edit tools
- Bash tool uses user data dir as CWD when available
- Add AgentID to config.Snapshot for per-user workspace setup
- Tests for sandbox validation, symlink escape, prefix confusion
vaayne added 4 commits March 20, 2026 20:57
…ent assignments (Phase 7)

- Add auth user management API endpoints under /api/auth/users/:
  - GET /api/auth/users — list all auth users with roles and identities
  - GET /api/auth/users/{id} — get user detail
  - PUT /api/auth/users/{id}/roles — assign/remove roles (cannot remove own admin)
  - GET/PUT /api/auth/users/{id}/agents — list/set agent assignments
  - PUT /api/auth/users/{id}/active — activate/deactivate (force logout on deactivate)
- Replace users page with tabbed layout: Auth Users (primary) + User Memory (legacy)
- Auth Users tab shows: username, roles badges, active status, linked identities
- User detail panel: roles management, identity list, agent assignments, activate/deactivate
- Preserve legacy /api/users endpoints for backward-compatible memory management
- All new endpoints are admin-only
- Tests: 13 new tests covering all endpoints, access control, self-protection guards
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5f4fbdf01a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 133 to 134
s.mux.HandleFunc("GET /api/sessions/{sessionID}/messages", s.getSessionMessages)
s.mux.HandleFunc("GET /api/sessions/{sessionID}/system-prompt", s.getSessionSystemPrompt)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict session APIs to the owning user or admins

After this commit, regular authenticated users can hit these routes because they are no longer wrapped in adminAPI(...). The handlers in internal/admin/sessions.go still return global data (ListInfo(..., true), raw messages, and system prompts) without checking UserFromContext, so any non-admin account can browse every user's conversation history and prompts via /api/sessions/*.

Useful? React with 👍 / 👎.

Comment on lines +94 to +96
// Link codes are shared between admin panel and channel bots. For now,
// create a standalone store since we might not have an admin panel.
linkCodes := auth.NewLinkCodeStore()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reuse the admin server's link-code store in gateway mode

When gateway runs with --admin-port, the profile page generates codes from the LinkCodeStore allocated inside admin.New(...), but the channel bots are wired to the separate store created here. In that deployment every code produced by the admin UI will be reported as invalid/expired by Telegram/QQ/Feishu, so identity linking never succeeds.

Useful? React with 👍 / 👎.

Comment on lines +51 to +54
async loadAllUsers() {
try {
const users = await api('GET', '/api/users')
this.allUsers = users || []

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Populate restricted-agent assignments from auth users

This modal loads /api/users, which is the legacy settings_users list used for memories, but POST /api/agents/{id}/users validates user_id against auth_users in assignAgentUser. As a result, admin-created accounts that have never sent a channel message never appear in the picker, and once the numeric IDs in the two tables diverge the UI can submit the wrong user for assignment.

Useful? React with 👍 / 👎.

@github-actions
Copy link

📊 Coverage Report

Total coverage: 44.9%

Per-package breakdown
github.com/vaayne/anna/cmd/anna/chat.go:13:                  2.9%
github.com/vaayne/anna/cmd/anna/commands.go:226:             7.7%
github.com/vaayne/anna/cmd/anna/commands.go:248:             0.0%
github.com/vaayne/anna/cmd/anna/commands.go:27:              100.0%
github.com/vaayne/anna/cmd/anna/commands.go:60:              68.1%
github.com/vaayne/anna/cmd/anna/gateway.go:225:              0.0%
github.com/vaayne/anna/cmd/anna/gateway.go:288:              37.5%
github.com/vaayne/anna/cmd/anna/gateway.go:29:               85.7%
github.com/vaayne/anna/cmd/anna/gateway.go:60:               19.5%
github.com/vaayne/anna/cmd/anna/main.go:9:                   0.0%
github.com/vaayne/anna/cmd/anna/models.go:104:               0.0%
github.com/vaayne/anna/cmd/anna/models.go:118:               0.0%
github.com/vaayne/anna/cmd/anna/models.go:131:               0.0%
github.com/vaayne/anna/cmd/anna/models.go:139:               100.0%
github.com/vaayne/anna/cmd/anna/models.go:154:               100.0%
github.com/vaayne/anna/cmd/anna/models.go:162:               0.0%
github.com/vaayne/anna/cmd/anna/models.go:177:               7.1%
github.com/vaayne/anna/cmd/anna/models.go:209:               11.1%
github.com/vaayne/anna/cmd/anna/models.go:228:               5.3%
github.com/vaayne/anna/cmd/anna/models.go:23:                0.0%
github.com/vaayne/anna/cmd/anna/models.go:266:               4.8%
github.com/vaayne/anna/cmd/anna/models.go:307:               0.0%
github.com/vaayne/anna/cmd/anna/models.go:68:                0.0%
github.com/vaayne/anna/cmd/anna/onboard.go:107:              0.0%
github.com/vaayne/anna/cmd/anna/onboard.go:24:               50.0%
github.com/vaayne/anna/cmd/anna/onboard.go:41:               0.0%
github.com/vaayne/anna/cmd/anna/plugin.go:130:               4.3%
github.com/vaayne/anna/cmd/anna/plugin.go:16:                50.0%
github.com/vaayne/anna/cmd/anna/plugin.go:177:               0.0%
github.com/vaayne/anna/cmd/anna/plugin.go:190:               0.0%
github.com/vaayne/anna/cmd/anna/plugin.go:199:               0.0%
github.com/vaayne/anna/cmd/anna/plugin.go:214:               0.0%
github.com/vaayne/anna/cmd/anna/plugin.go:31:                50.0%
github.com/vaayne/anna/cmd/anna/plugin.go:41:                0.0%
github.com/vaayne/anna/cmd/anna/plugin.go:65:                3.6%
github.com/vaayne/anna/cmd/anna/skills.go:114:               25.0%
github.com/vaayne/anna/cmd/anna/skills.go:133:               0.0%
github.com/vaayne/anna/cmd/anna/skills.go:176:               0.0%
github.com/vaayne/anna/cmd/anna/skills.go:19:                50.0%
github.com/vaayne/anna/cmd/anna/skills.go:210:               6.7%
github.com/vaayne/anna/cmd/anna/skills.go:36:                5.3%
github.com/vaayne/anna/cmd/anna/skills.go:79:                5.9%
github.com/vaayne/anna/cmd/anna/version.go:101:              75.0%
github.com/vaayne/anna/cmd/anna/version.go:109:              0.0%
github.com/vaayne/anna/cmd/anna/version.go:117:              0.0%
github.com/vaayne/anna/cmd/anna/version.go:151:              0.0%
github.com/vaayne/anna/cmd/anna/version.go:185:              0.0%
github.com/vaayne/anna/cmd/anna/version.go:197:              0.0%
github.com/vaayne/anna/cmd/anna/version.go:202:              0.0%
github.com/vaayne/anna/cmd/anna/version.go:235:              0.0%
github.com/vaayne/anna/cmd/anna/version.go:271:              0.0%
github.com/vaayne/anna/cmd/anna/version.go:282:              0.0%
github.com/vaayne/anna/cmd/anna/version.go:327:              0.0%
github.com/vaayne/anna/cmd/anna/version.go:360:              0.0%
github.com/vaayne/anna/cmd/anna/version.go:376:              0.0%
github.com/vaayne/anna/cmd/anna/version.go:446:              0.0%
github.com/vaayne/anna/cmd/anna/version.go:462:              0.0%
github.com/vaayne/anna/cmd/anna/version.go:469:              75.0%
github.com/vaayne/anna/cmd/anna/version.go:54:               33.3%
github.com/vaayne/anna/cmd/anna/version.go:65:               6.2%
github.com/vaayne/anna/internal/admin/agents.go:110:         0.0%
github.com/vaayne/anna/internal/admin/agents.go:121:         78.6%
github.com/vaayne/anna/internal/admin/agents.go:13:          61.5%
github.com/vaayne/anna/internal/admin/agents.go:148:         47.4%
github.com/vaayne/anna/internal/admin/agents.go:184:         63.6%
github.com/vaayne/anna/internal/admin/agents.go:206:         90.0%
github.com/vaayne/anna/internal/admin/agents.go:237:         66.7%
github.com/vaayne/anna/internal/admin/agents.go:36:          61.1%
github.com/vaayne/anna/internal/admin/agents.go:63:          83.3%
github.com/vaayne/anna/internal/admin/agents.go:85:          52.9%
github.com/vaayne/anna/internal/admin/auth.go:108:           71.1%
github.com/vaayne/anna/internal/admin/auth.go:12:            57.4%
github.com/vaayne/anna/internal/admin/auth.go:182:           100.0%
github.com/vaayne/anna/internal/admin/auth.go:192:           60.0%
github.com/vaayne/anna/internal/admin/auth.go:207:           100.0%
github.com/vaayne/anna/internal/admin/auth.go:216:           66.7%
github.com/vaayne/anna/internal/admin/auth_users.go:158:     55.6%
github.com/vaayne/anna/internal/admin/auth_users.go:175:     67.7%
github.com/vaayne/anna/internal/admin/auth_users.go:236:     65.2%
github.com/vaayne/anna/internal/admin/auth_users.go:24:      81.8%
github.com/vaayne/anna/internal/admin/auth_users.go:53:      66.7%
github.com/vaayne/anna/internal/admin/auth_users.go:74:      69.2%
github.com/vaayne/anna/internal/admin/auth_users.go:97:      57.6%
github.com/vaayne/anna/internal/admin/channels.go:18:        0.0%
github.com/vaayne/anna/internal/admin/channels.go:28:        0.0%
github.com/vaayne/anna/internal/admin/channels.go:9:         0.0%
github.com/vaayne/anna/internal/admin/embed.go:15:           75.0%
github.com/vaayne/anna/internal/admin/middleware.go:130:     100.0%
github.com/vaayne/anna/internal/admin/middleware.go:146:     100.0%
github.com/vaayne/anna/internal/admin/middleware.go:155:     100.0%
github.com/vaayne/anna/internal/admin/middleware.go:27:      100.0%
github.com/vaayne/anna/internal/admin/middleware.go:33:      100.0%
github.com/vaayne/anna/internal/admin/middleware.go:40:      67.4%
github.com/vaayne/anna/internal/admin/models.go:11:          0.0%
github.com/vaayne/anna/internal/admin/profile.go:11:         50.0%
github.com/vaayne/anna/internal/admin/profile.go:124:        59.1%
github.com/vaayne/anna/internal/admin/profile.go:29:         54.1%
github.com/vaayne/anna/internal/admin/profile.go:92:         69.2%
github.com/vaayne/anna/internal/admin/providers.go:144:      0.0%
github.com/vaayne/anna/internal/admin/providers.go:15:       60.0%
github.com/vaayne/anna/internal/admin/providers.go:170:      0.0%
github.com/vaayne/anna/internal/admin/providers.go:24:       46.2%
github.com/vaayne/anna/internal/admin/providers.go:44:       0.0%
github.com/vaayne/anna/internal/admin/providers.go:54:       0.0%
github.com/vaayne/anna/internal/admin/providers.go:72:       0.0%
github.com/vaayne/anna/internal/admin/providers.go:81:       0.0%
github.com/vaayne/anna/internal/admin/render.go:11:          66.7%
github.com/vaayne/anna/internal/admin/render.go:18:          100.0%
github.com/vaayne/anna/internal/admin/render.go:22:          100.0%
github.com/vaayne/anna/internal/admin/render.go:26:          100.0%
github.com/vaayne/anna/internal/admin/render.go:30:          100.0%
github.com/vaayne/anna/internal/admin/render.go:34:          100.0%
github.com/vaayne/anna/internal/admin/render.go:38:          100.0%
github.com/vaayne/anna/internal/admin/render.go:42:          100.0%
github.com/vaayne/anna/internal/admin/render.go:46:          100.0%
github.com/vaayne/anna/internal/admin/render.go:52:          87.5%
github.com/vaayne/anna/internal/admin/scheduler.go:146:      0.0%
github.com/vaayne/anna/internal/admin/scheduler.go:162:      0.0%
github.com/vaayne/anna/internal/admin/scheduler.go:183:      0.0%
github.com/vaayne/anna/internal/admin/scheduler.go:208:      0.0%
github.com/vaayne/anna/internal/admin/scheduler.go:29:       0.0%
github.com/vaayne/anna/internal/admin/scheduler.go:42:       0.0%
github.com/vaayne/anna/internal/admin/scheduler.go:88:       0.0%
github.com/vaayne/anna/internal/admin/server.go:157:         62.5%
github.com/vaayne/anna/internal/admin/server.go:171:         0.0%
github.com/vaayne/anna/internal/admin/server.go:176:         100.0%
github.com/vaayne/anna/internal/admin/server.go:181:         100.0%
github.com/vaayne/anna/internal/admin/server.go:198:         100.0%
github.com/vaayne/anna/internal/admin/server.go:208:         100.0%
github.com/vaayne/anna/internal/admin/server.go:214:         100.0%
github.com/vaayne/anna/internal/admin/server.go:221:         100.0%
github.com/vaayne/anna/internal/admin/server.go:32:          98.5%
github.com/vaayne/anna/internal/admin/sessions.go:103:       0.0%
github.com/vaayne/anna/internal/admin/sessions.go:125:       0.0%
github.com/vaayne/anna/internal/admin/sessions.go:166:       0.0%
github.com/vaayne/anna/internal/admin/sessions.go:189:       0.0%
github.com/vaayne/anna/internal/admin/sessions.go:198:       0.0%
github.com/vaayne/anna/internal/admin/sessions.go:237:       0.0%
github.com/vaayne/anna/internal/admin/sessions.go:251:       0.0%
github.com/vaayne/anna/internal/admin/sessions.go:33:        0.0%
github.com/vaayne/anna/internal/admin/sessions.go:46:        0.0%
github.com/vaayne/anna/internal/admin/sessions.go:63:        0.0%
github.com/vaayne/anna/internal/admin/settings.go:24:        0.0%
github.com/vaayne/anna/internal/admin/settings.go:8:         0.0%
github.com/vaayne/anna/internal/admin/tools.go:22:           0.0%
github.com/vaayne/anna/internal/admin/tools.go:31:           0.0%
github.com/vaayne/anna/internal/admin/tools.go:61:           0.0%
github.com/vaayne/anna/internal/admin/ui/components_templ.go:122: 0.0%
github.com/vaayne/anna/internal/admin/ui/components_templ.go:12: 0.0%
github.com/vaayne/anna/internal/admin/ui/components_templ.go:182: 0.0%
github.com/vaayne/anna/internal/admin/ui/components_templ.go:206: 0.0%
github.com/vaayne/anna/internal/admin/ui/components_templ.go:78: 0.0%
github.com/vaayne/anna/internal/admin/ui/layout_templ.go:11: 0.0%
github.com/vaayne/anna/internal/admin/ui/layout_templ.go:87: 0.0%
github.com/vaayne/anna/internal/admin/ui/loginlayout_templ.go:11: 0.0%
github.com/vaayne/anna/internal/admin/ui/navbar_templ.go:279: 0.0%
github.com/vaayne/anna/internal/admin/ui/navbar_templ.go:28: 0.0%
github.com/vaayne/anna/internal/admin/ui/navbar_templ.go:38: 0.0%
github.com/vaayne/anna/internal/admin/ui/pages/agents_templ.go:13: 0.0%
github.com/vaayne/anna/internal/admin/ui/pages/agents_templ.go:209: 0.0%
github.com/vaayne/anna/internal/admin/ui/pages/channels_templ.go:13: 0.0%
github.com/vaayne/anna/internal/admin/ui/pages/channels_templ.go:545: 0.0%
github.com/vaayne/anna/internal/admin/ui/pages/login_templ.go:11: 0.0%
github.com/vaayne/anna/internal/admin/ui/pages/profile_templ.go:13: 0.0%
github.com/vaayne/anna/internal/admin/ui/pages/providers_templ.go:13: 0.0%
github.com/vaayne/anna/internal/admin/ui/pages/scheduler_templ.go:13: 0.0%
github.com/vaayne/anna/internal/admin/ui/pages/sessions_templ.go:13: 0.0%
github.com/vaayne/anna/internal/admin/ui/pages/settings_templ.go:13: 0.0%
github.com/vaayne/anna/internal/admin/ui/pages/users_templ.go:13: 0.0%
github.com/vaayne/anna/internal/admin/users.go:17:           0.0%
github.com/vaayne/anna/internal/admin/users.go:37:           0.0%
github.com/vaayne/anna/internal/admin/users.go:51:           0.0%
github.com/vaayne/anna/internal/admin/users.go:72:           0.0%
github.com/vaayne/anna/internal/admin/users.go:8:            60.0%
github.com/vaayne/anna/internal/agent/engine/continue.go:12: 60.0%
github.com/vaayne/anna/internal/agent/engine/engine.go:122:  85.1%
github.com/vaayne/anna/internal/agent/engine/engine.go:20:   91.7%
github.com/vaayne/anna/internal/agent/engine/engine.go:212:  88.9%
github.com/vaayne/anna/internal/agent/engine/engine.go:227:  100.0%
github.com/vaayne/anna/internal/agent/engine/engine.go:42:   94.6%
github.com/vaayne/anna/internal/agent/engine/events.go:13:   100.0%
github.com/vaayne/anna/internal/agent/engine/events.go:20:   100.0%
github.com/vaayne/anna/internal/agent/engine/events.go:28:   100.0%
github.com/vaayne/anna/internal/agent/engine/events.go:35:   100.0%
github.com/vaayne/anna/internal/agent/engine/events.go:42:   100.0%
github.com/vaayne/anna/internal/agent/engine/events.go:49:   100.0%
github.com/vaayne/anna/internal/agent/engine/events.go:56:   100.0%
github.com/vaayne/anna/internal/agent/engine/events.go:63:   100.0%
github.com/vaayne/anna/internal/agent/engine/events.go:68:   100.0%
github.com/vaayne/anna/internal/agent/engine/events.go:75:   100.0%
github.com/vaayne/anna/internal/agent/engine/tool_execution.go:18: 73.5%
github.com/vaayne/anna/internal/agent/factory.go:20:         9.5%
github.com/vaayne/anna/internal/agent/factory.go:85:         0.0%
github.com/vaayne/anna/internal/agent/pool.go:138:           100.0%
github.com/vaayne/anna/internal/agent/pool.go:147:           100.0%
github.com/vaayne/anna/internal/agent/pool.go:159:           75.0%
github.com/vaayne/anna/internal/agent/pool.go:169:           100.0%
github.com/vaayne/anna/internal/agent/pool.go:185:           83.3%
github.com/vaayne/anna/internal/agent/pool.go:197:           89.5%
github.com/vaayne/anna/internal/agent/pool.go:235:           100.0%
github.com/vaayne/anna/internal/agent/pool.go:246:           81.2%
github.com/vaayne/anna/internal/agent/pool.go:38:            100.0%
github.com/vaayne/anna/internal/agent/pool.go:402:           100.0%
github.com/vaayne/anna/internal/agent/pool.go:410:           100.0%
github.com/vaayne/anna/internal/agent/pool.go:417:           80.0%
github.com/vaayne/anna/internal/agent/pool.go:450:           91.3%
github.com/vaayne/anna/internal/agent/pool.go:57:            100.0%
github.com/vaayne/anna/internal/agent/pool.go:62:            100.0%
github.com/vaayne/anna/internal/agent/pool.go:71:            83.3%
github.com/vaayne/anna/internal/agent/pool.go:88:            75.0%
github.com/vaayne/anna/internal/agent/pool.go:98:            100.0%
github.com/vaayne/anna/internal/agent/pool_compaction.go:12: 100.0%
github.com/vaayne/anna/internal/agent/pool_compaction.go:17: 80.0%
github.com/vaayne/anna/internal/agent/pool_compaction.go:37: 100.0%
github.com/vaayne/anna/internal/agent/pool_manager.go:102:   75.0%
github.com/vaayne/anna/internal/agent/pool_manager.go:131:   80.8%
github.com/vaayne/anna/internal/agent/pool_manager.go:191:   80.0%
github.com/vaayne/anna/internal/agent/pool_manager.go:201:   81.8%
github.com/vaayne/anna/internal/agent/pool_manager.go:27:    0.0%
github.com/vaayne/anna/internal/agent/pool_manager.go:34:    0.0%
github.com/vaayne/anna/internal/agent/pool_manager.go:41:    0.0%
github.com/vaayne/anna/internal/agent/pool_manager.go:48:    0.0%
github.com/vaayne/anna/internal/agent/pool_manager.go:55:    0.0%
github.com/vaayne/anna/internal/agent/pool_manager.go:78:    75.0%
github.com/vaayne/anna/internal/agent/pool_manager.go:94:    100.0%
github.com/vaayne/anna/internal/agent/pool_options.go:14:    100.0%
github.com/vaayne/anna/internal/agent/pool_options.go:21:    100.0%
github.com/vaayne/anna/internal/agent/pool_options.go:28:    100.0%
github.com/vaayne/anna/internal/agent/pool_options.go:35:    100.0%
github.com/vaayne/anna/internal/agent/pool_options.go:42:    100.0%
github.com/vaayne/anna/internal/agent/pool_options.go:49:    0.0%
github.com/vaayne/anna/internal/agent/pool_options.go:56:    100.0%
github.com/vaayne/anna/internal/agent/pool_options.go:71:    100.0%
github.com/vaayne/anna/internal/agent/pool_reaper.go:13:     83.3%
github.com/vaayne/anna/internal/agent/pool_reaper.go:28:     89.5%
github.com/vaayne/anna/internal/agent/runner/builtin/embed.go:17: 0.0%
github.com/vaayne/anna/internal/agent/runner/gorunner.go:107: 100.0%
github.com/vaayne/anna/internal/agent/runner/gorunner.go:144: 100.0%
github.com/vaayne/anna/internal/agent/runner/gorunner.go:147: 100.0%
github.com/vaayne/anna/internal/agent/runner/gorunner.go:154: 100.0%
github.com/vaayne/anna/internal/agent/runner/gorunner.go:157: 100.0%
github.com/vaayne/anna/internal/agent/runner/gorunner.go:170: 94.4%
github.com/vaayne/anna/internal/agent/runner/gorunner.go:221: 90.5%
github.com/vaayne/anna/internal/agent/runner/gorunner.go:263: 100.0%
github.com/vaayne/anna/internal/agent/runner/gorunner.go:52: 95.0%
github.com/vaayne/anna/internal/agent/runner/prompt.go:107:  95.0%
github.com/vaayne/anna/internal/agent/runner/prompt.go:147:  100.0%
github.com/vaayne/anna/internal/agent/runner/prompt.go:37:   75.9%
github.com/vaayne/anna/internal/agent/runner/prompt.go:92:   85.7%
github.com/vaayne/anna/internal/agent/runner/runner.go:62:   100.0%
github.com/vaayne/anna/internal/agent/runner/runner.go:86:   75.0%
github.com/vaayne/anna/internal/agent/runner/skill.go:114:   100.0%
github.com/vaayne/anna/internal/agent/runner/skill.go:123:   85.7%
github.com/vaayne/anna/internal/agent/runner/skill.go:165:   85.7%
github.com/vaayne/anna/internal/agent/runner/skill.go:201:   91.7%
github.com/vaayne/anna/internal/agent/runner/skill.go:227:   100.0%
github.com/vaayne/anna/internal/agent/runner/skill.go:258:   91.7%
github.com/vaayne/anna/internal/agent/runner/skill.go:278:   100.0%
github.com/vaayne/anna/internal/agent/runner/skill.go:44:    100.0%
github.com/vaayne/anna/internal/agent/runner/skill.go:53:    93.1%
github.com/vaayne/anna/internal/agent/runner/stream_proxy.go:17: 80.0%
github.com/vaayne/anna/internal/agent/runner/stream_proxy.go:27: 82.4%
github.com/vaayne/anna/internal/agent/runner/stream_proxy.go:57: 100.0%
github.com/vaayne/anna/internal/agent/session.go:21:         100.0%
github.com/vaayne/anna/internal/agent/session.go:33:         100.0%
github.com/vaayne/anna/internal/agent/tool/bash.go:105:      33.3%
github.com/vaayne/anna/internal/agent/tool/bash.go:121:      85.7%
github.com/vaayne/anna/internal/agent/tool/bash.go:133:      40.0%
github.com/vaayne/anna/internal/agent/tool/bash.go:23:       100.0%
github.com/vaayne/anna/internal/agent/tool/bash.go:40:       100.0%
github.com/vaayne/anna/internal/agent/tool/bash.go:85:       100.0%
github.com/vaayne/anna/internal/agent/tool/delegate.go:144:  88.9%
github.com/vaayne/anna/internal/agent/tool/delegate.go:221:  100.0%
github.com/vaayne/anna/internal/agent/tool/delegate.go:260:  100.0%
github.com/vaayne/anna/internal/agent/tool/delegate.go:276:  100.0%
github.com/vaayne/anna/internal/agent/tool/delegate.go:284:  89.7%
github.com/vaayne/anna/internal/agent/tool/delegate.go:40:   100.0%
github.com/vaayne/anna/internal/agent/tool/delegate.go:45:   100.0%
github.com/vaayne/anna/internal/agent/tool/delegate.go:91:   100.0%
github.com/vaayne/anna/internal/agent/tool/delegate.go:95:   90.9%
github.com/vaayne/anna/internal/agent/tool/edit.go:15:       100.0%
github.com/vaayne/anna/internal/agent/tool/edit.go:40:       85.0%
github.com/vaayne/anna/internal/agent/tool/read.go:107:      100.0%
github.com/vaayne/anna/internal/agent/tool/read.go:124:      76.2%
github.com/vaayne/anna/internal/agent/tool/read.go:160:      71.4%
github.com/vaayne/anna/internal/agent/tool/read.go:16:       100.0%
github.com/vaayne/anna/internal/agent/tool/read.go:172:      71.4%
github.com/vaayne/anna/internal/agent/tool/read.go:41:       94.4%
github.com/vaayne/anna/internal/agent/tool/sandbox.go:19:    100.0%
github.com/vaayne/anna/internal/agent/tool/sandbox.go:23:    100.0%
github.com/vaayne/anna/internal/agent/tool/sandbox.go:36:    100.0%
github.com/vaayne/anna/internal/agent/tool/tool.go:28:       93.3%
github.com/vaayne/anna/internal/agent/tool/tool.go:54:       0.0%
github.com/vaayne/anna/internal/agent/tool/tool.go:63:       100.0%
github.com/vaayne/anna/internal/agent/tool/tool.go:68:       100.0%
github.com/vaayne/anna/internal/agent/tool/tool.go:77:       100.0%
github.com/vaayne/anna/internal/agent/tool/tool.go:83:       100.0%
github.com/vaayne/anna/internal/agent/tool/truncate.go:102:  100.0%
github.com/vaayne/anna/internal/agent/tool/truncate.go:119:  66.7%
github.com/vaayne/anna/internal/agent/tool/truncate.go:132:  100.0%
github.com/vaayne/anna/internal/agent/tool/truncate.go:144:  94.1%
github.com/vaayne/anna/internal/agent/tool/truncate.go:22:   100.0%
github.com/vaayne/anna/internal/agent/tool/truncate.go:31:   100.0%
github.com/vaayne/anna/internal/agent/tool/truncate.go:42:   100.0%
github.com/vaayne/anna/internal/agent/tool/truncate.go:52:   100.0%
github.com/vaayne/anna/internal/agent/tool/truncate.go:58:   100.0%
github.com/vaayne/anna/internal/agent/tool/truncate.go:65:   92.9%
github.com/vaayne/anna/internal/agent/tool/truncate.go:89:   100.0%
github.com/vaayne/anna/internal/agent/tool/webfetch.go:109:  66.7%
github.com/vaayne/anna/internal/agent/tool/webfetch.go:118:  68.0%
github.com/vaayne/anna/internal/agent/tool/webfetch.go:164:  66.7%
github.com/vaayne/anna/internal/agent/tool/webfetch.go:175:  40.0%
github.com/vaayne/anna/internal/agent/tool/webfetch.go:188:  81.8%
github.com/vaayne/anna/internal/agent/tool/webfetch.go:206:  0.0%
github.com/vaayne/anna/internal/agent/tool/webfetch.go:214:  0.0%
github.com/vaayne/anna/internal/agent/tool/webfetch.go:237:  0.0%
github.com/vaayne/anna/internal/agent/tool/webfetch.go:263:  90.0%
github.com/vaayne/anna/internal/agent/tool/webfetch.go:282:  75.0%
github.com/vaayne/anna/internal/agent/tool/webfetch.go:40:   100.0%
github.com/vaayne/anna/internal/agent/tool/webfetch.go:46:   100.0%
github.com/vaayne/anna/internal/agent/tool/webfetch.go:69:   77.3%
github.com/vaayne/anna/internal/agent/tool/write.go:15:      100.0%
github.com/vaayne/anna/internal/agent/tool/write.go:36:      80.0%
github.com/vaayne/anna/internal/agent/workspace.go:12:       83.3%
github.com/vaayne/anna/internal/agent/workspace.go:30:       80.0%
github.com/vaayne/anna/internal/agent/workspace.go:48:       100.0%
github.com/vaayne/anna/internal/agent/workspace.go:53:       100.0%
github.com/vaayne/anna/internal/ai/events.go:103:            100.0%
github.com/vaayne/anna/internal/ai/events.go:111:            100.0%
github.com/vaayne/anna/internal/ai/events.go:119:            100.0%
github.com/vaayne/anna/internal/ai/events.go:124:            100.0%
github.com/vaayne/anna/internal/ai/events.go:16:             100.0%
github.com/vaayne/anna/internal/ai/events.go:24:             100.0%
github.com/vaayne/anna/internal/ai/events.go:33:             100.0%
github.com/vaayne/anna/internal/ai/events.go:42:             100.0%
github.com/vaayne/anna/internal/ai/events.go:50:             100.0%
github.com/vaayne/anna/internal/ai/events.go:59:             100.0%
github.com/vaayne/anna/internal/ai/events.go:68:             100.0%
github.com/vaayne/anna/internal/ai/events.go:76:             100.0%
github.com/vaayne/anna/internal/ai/events.go:87:             100.0%
github.com/vaayne/anna/internal/ai/events.go:96:             100.0%
github.com/vaayne/anna/internal/ai/message.go:101:           100.0%
github.com/vaayne/anna/internal/ai/message.go:111:           100.0%
github.com/vaayne/anna/internal/ai/message.go:26:            100.0%
github.com/vaayne/anna/internal/ai/message.go:35:            100.0%
github.com/vaayne/anna/internal/ai/message.go:43:            100.0%
github.com/vaayne/anna/internal/ai/message.go:46:            100.0%
github.com/vaayne/anna/internal/ai/message.go:58:            100.0%
github.com/vaayne/anna/internal/ai/message.go:72:            100.0%
github.com/vaayne/anna/internal/ai/message.go:86:            100.0%
github.com/vaayne/anna/internal/ai/message.go:98:            100.0%
github.com/vaayne/anna/internal/ai/provider.go:162:          100.0%
github.com/vaayne/anna/internal/ai/provider.go:167:          100.0%
github.com/vaayne/anna/internal/ai/provider.go:172:          100.0%
github.com/vaayne/anna/internal/ai/provider.go:177:          100.0%
github.com/vaayne/anna/internal/ai/provider.go:187:          100.0%
github.com/vaayne/anna/internal/ai/provider.go:195:          100.0%
github.com/vaayne/anna/internal/ai/provider.go:36:           100.0%
github.com/vaayne/anna/internal/ai/provider.go:46:           100.0%
github.com/vaayne/anna/internal/ai/provider.go:54:           100.0%
github.com/vaayne/anna/internal/ai/provider.go:61:           100.0%
github.com/vaayne/anna/internal/ai/provider.go:69:           100.0%
github.com/vaayne/anna/internal/ai/provider.go:78:           100.0%
github.com/vaayne/anna/internal/ai/provider.go:87:           97.1%
github.com/vaayne/anna/internal/ai/providers/anthropic/client.go:24: 100.0%
github.com/vaayne/anna/internal/ai/providers/anthropic/client.go:36: 100.0%
github.com/vaayne/anna/internal/ai/providers/anthropic/client.go:39: 0.0%
github.com/vaayne/anna/internal/ai/providers/anthropic/client.go:56: 0.0%
github.com/vaayne/anna/internal/ai/providers/anthropic/client.go:61: 0.0%
github.com/vaayne/anna/internal/ai/providers/anthropic/client.go:81: 100.0%
github.com/vaayne/anna/internal/ai/providers/anthropic/convert_messages.go:10: 100.0%
github.com/vaayne/anna/internal/ai/providers/anthropic/convert_messages.go:25: 100.0%
github.com/vaayne/anna/internal/ai/providers/anthropic/convert_messages.go:45: 100.0%
github.com/vaayne/anna/internal/ai/providers/anthropic/convert_messages.go:60: 100.0%
github.com/vaayne/anna/internal/ai/providers/anthropic/options.go:10: 100.0%
github.com/vaayne/anna/internal/ai/providers/anthropic/options.go:37: 100.0%
github.com/vaayne/anna/internal/ai/providers/anthropic/stream.go:21: 76.0%
github.com/vaayne/anna/internal/ai/providers/anthropic/stream.go:77: 100.0%
github.com/vaayne/anna/internal/ai/providers/anthropic/stream.go:9: 0.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/client.go:105: 0.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/client.go:110: 0.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/client.go:130: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/client.go:27: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/client.go:42: 0.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/client.go:59: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/client.go:79: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/client.go:84: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/client.go:87: 0.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/convert_messages.go:13: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/convert_messages.go:34: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/convert_messages.go:68: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/options.go:11: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/options.go:39: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/stream.go:21: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/stream.go:74: 40.0%
github.com/vaayne/anna/internal/ai/providers/openai-response/stream.go:9: 0.0%
github.com/vaayne/anna/internal/ai/providers/openai/client.go:24: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai/client.go:36: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai/client.go:39: 0.0%
github.com/vaayne/anna/internal/ai/providers/openai/client.go:57: 0.0%
github.com/vaayne/anna/internal/ai/providers/openai/client.go:62: 0.0%
github.com/vaayne/anna/internal/ai/providers/openai/client.go:82: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai/convert_messages.go:13: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai/convert_messages.go:33: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai/convert_messages.go:66: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai/options.go:11: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai/options.go:33: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai/stream.go:22: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai/stream.go:57: 100.0%
github.com/vaayne/anna/internal/ai/providers/openai/stream.go:9: 0.0%
github.com/vaayne/anna/internal/ai/providers/register_builtins.go:11: 0.0%
github.com/vaayne/anna/internal/ai/transform.go:42:          85.7%
github.com/vaayne/anna/internal/ai/transform.go:6:           93.8%
github.com/vaayne/anna/internal/auth/authdb/store.go:113:    100.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:121:    85.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:133:    66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:144:    66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:153:    66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:163:    66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:173:    85.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:187:    100.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:200:    100.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:208:    75.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:219:    85.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:22:     100.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:231:    66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:240:    90.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:267:    100.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:275:    85.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:287:    85.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:28:     100.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:299:    66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:320:    66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:329:    66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:339:    66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:349:    83.3%
github.com/vaayne/anna/internal/auth/authdb/store.go:359:    83.3%
github.com/vaayne/anna/internal/auth/authdb/store.go:371:    75.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:383:    100.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:391:    66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:398:    66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:39:     100.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:405:    66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:412:    66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:424:    75.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:432:    100.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:443:    100.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:453:    100.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:464:    100.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:47:     75.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:480:    100.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:55:     85.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:67:     66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:83:     66.7%
github.com/vaayne/anna/internal/auth/authdb/store.go:90:     100.0%
github.com/vaayne/anna/internal/auth/authdb/store.go:96:     85.7%
github.com/vaayne/anna/internal/auth/condition.go:116:       100.0%
github.com/vaayne/anna/internal/auth/condition.go:166:       100.0%
github.com/vaayne/anna/internal/auth/condition.go:179:       88.2%
github.com/vaayne/anna/internal/auth/condition.go:212:       100.0%
github.com/vaayne/anna/internal/auth/condition.go:217:       90.9%
github.com/vaayne/anna/internal/auth/condition.go:29:        92.9%
github.com/vaayne/anna/internal/auth/condition.go:59:        100.0%
github.com/vaayne/anna/internal/auth/condition.go:78:        88.9%
github.com/vaayne/anna/internal/auth/condition.go:98:        85.7%
github.com/vaayne/anna/internal/auth/engine.go:105:          100.0%
github.com/vaayne/anna/internal/auth/engine.go:118:          100.0%
github.com/vaayne/anna/internal/auth/engine.go:149:          92.3%
github.com/vaayne/anna/internal/auth/engine.go:176:          92.3%
github.com/vaayne/anna/internal/auth/engine.go:24:           87.5%
github.com/vaayne/anna/internal/auth/engine.go:42:           100.0%
github.com/vaayne/anna/internal/auth/engine.go:61:           100.0%
github.com/vaayne/anna/internal/auth/engine.go:96:           100.0%
github.com/vaayne/anna/internal/auth/linkcode.go:34:         100.0%
github.com/vaayne/anna/internal/auth/linkcode.go:40:         100.0%
github.com/vaayne/anna/internal/auth/linkcode.go:53:         87.5%
github.com/vaayne/anna/internal/auth/linkcode.go:68:         100.0%
github.com/vaayne/anna/internal/auth/linkcode.go:82:         80.0%
github.com/vaayne/anna/internal/auth/linkcode.go:94:         100.0%
github.com/vaayne/anna/internal/auth/password.go:17:         100.0%
github.com/vaayne/anna/internal/auth/password.go:8:          75.0%
github.com/vaayne/anna/internal/auth/ratelimit.go:117:       88.9%
github.com/vaayne/anna/internal/auth/ratelimit.go:136:       100.0%
github.com/vaayne/anna/internal/auth/ratelimit.go:44:        100.0%
github.com/vaayne/anna/internal/auth/ratelimit.go:50:        71.4%
github.com/vaayne/anna/internal/auth/ratelimit.go:77:        77.8%
github.com/vaayne/anna/internal/auth/ratelimit.go:95:        90.9%
github.com/vaayne/anna/internal/auth/sandbox.go:13:          83.3%
github.com/vaayne/anna/internal/auth/sandbox.go:43:          92.3%
github.com/vaayne/anna/internal/auth/seed.go:130:            86.7%
github.com/vaayne/anna/internal/auth/seed.go:159:            66.7%
github.com/vaayne/anna/internal/auth/session.go:27:          75.0%
github.com/vaayne/anna/internal/auth/session.go:37:          100.0%
github.com/vaayne/anna/internal/auth/session.go:52:          100.0%
github.com/vaayne/anna/internal/auth/session.go:66:          100.0%
github.com/vaayne/anna/internal/channel/agent_command.go:17: 0.0%
github.com/vaayne/anna/internal/channel/agent_command.go:22: 0.0%
github.com/vaayne/anna/internal/channel/agent_command.go:29: 0.0%
github.com/vaayne/anna/internal/channel/agent_command.go:54: 0.0%
github.com/vaayne/anna/internal/channel/cli/chat.go:126:     75.0%
github.com/vaayne/anna/internal/channel/cli/chat.go:136:     16.7%
github.com/vaayne/anna/internal/channel/cli/chat.go:169:     0.0%
github.com/vaayne/anna/internal/channel/cli/chat.go:180:     0.0%
github.com/vaayne/anna/internal/channel/cli/chat.go:184:     38.5%
github.com/vaayne/anna/internal/channel/cli/chat.go:88:      84.6%
github.com/vaayne/anna/internal/channel/cli/chat_input.go:107: 20.0%
github.com/vaayne/anna/internal/channel/cli/chat_input.go:11: 43.4%
github.com/vaayne/anna/internal/channel/cli/chat_input.go:82: 72.7%
github.com/vaayne/anna/internal/channel/cli/chat_picker.go:96: 0.0%
github.com/vaayne/anna/internal/channel/cli/chat_picker.go:9: 0.0%
github.com/vaayne/anna/internal/channel/cli/chat_view.go:16: 77.3%
github.com/vaayne/anna/internal/channel/cli/chat_view.go:66: 66.7%
github.com/vaayne/anna/internal/channel/cli/chat_view.go:78: 100.0%
github.com/vaayne/anna/internal/channel/cli/chat_view.go:85: 100.0%
github.com/vaayne/anna/internal/channel/cli/chat_view.go:88: 0.0%
github.com/vaayne/anna/internal/channel/cli/chat_view.go:96: 0.0%
github.com/vaayne/anna/internal/channel/cli/cli.go:29:       0.0%
github.com/vaayne/anna/internal/channel/cli/cli.go:60:       0.0%
github.com/vaayne/anna/internal/channel/cli/command.go:22:   0.0%
github.com/vaayne/anna/internal/channel/cli/command.go:36:   0.0%
github.com/vaayne/anna/internal/channel/cli/model.go:17:     0.0%
github.com/vaayne/anna/internal/channel/cli/model.go:25:     0.0%
github.com/vaayne/anna/internal/channel/cli/model.go:41:     0.0%
github.com/vaayne/anna/internal/channel/command.go:22:       47.1%
github.com/vaayne/anna/internal/channel/command.go:63:       100.0%
github.com/vaayne/anna/internal/channel/command.go:68:       100.0%
github.com/vaayne/anna/internal/channel/command.go:78:       100.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:120: 0.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:156: 100.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:164: 0.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:196: 100.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:200: 31.2%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:239: 100.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:249: 0.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:280: 100.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:287: 100.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:305: 100.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:318: 100.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:347: 90.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:35: 100.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:369: 100.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:77: 0.0%
github.com/vaayne/anna/internal/channel/feishu/feishu.go:86: 90.9%
github.com/vaayne/anna/internal/channel/feishu/handler.go:139: 0.0%
github.com/vaayne/anna/internal/channel/feishu/handler.go:159: 0.0%
github.com/vaayne/anna/internal/channel/feishu/handler.go:189: 100.0%
github.com/vaayne/anna/internal/channel/feishu/handler.go:19: 0.0%
github.com/vaayne/anna/internal/channel/feishu/handler.go:203: 0.0%
github.com/vaayne/anna/internal/channel/feishu/handler.go:238: 69.2%
github.com/vaayne/anna/internal/channel/feishu/handler.go:261: 0.0%
github.com/vaayne/anna/internal/channel/feishu/handler.go:281: 100.0%
github.com/vaayne/anna/internal/channel/feishu/handler.go:95: 0.0%
github.com/vaayne/anna/internal/channel/feishu/model.go:106: 100.0%
github.com/vaayne/anna/internal/channel/feishu/model.go:22:  100.0%
github.com/vaayne/anna/internal/channel/feishu/model.go:46:  53.3%
github.com/vaayne/anna/internal/channel/feishu/model.go:75:  100.0%
github.com/vaayne/anna/internal/channel/feishu/model.go:90:  100.0%
github.com/vaayne/anna/internal/channel/feishu/render.go:17: 0.0%
github.com/vaayne/anna/internal/channel/feishu/render.go:44: 18.2%
github.com/vaayne/anna/internal/channel/feishu/render.go:95: 100.0%
github.com/vaayne/anna/internal/channel/feishu/stream.go:129: 0.0%
github.com/vaayne/anna/internal/channel/feishu/stream.go:152: 0.0%
github.com/vaayne/anna/internal/channel/feishu/stream.go:172: 78.6%
github.com/vaayne/anna/internal/channel/feishu/stream.go:27: 100.0%
github.com/vaayne/anna/internal/channel/feishu/stream.go:53: 0.0%
github.com/vaayne/anna/internal/channel/identity.go:145:     83.3%
github.com/vaayne/anna/internal/channel/identity.go:173:     86.2%
github.com/vaayne/anna/internal/channel/identity.go:247:     75.0%
github.com/vaayne/anna/internal/channel/identity.go:36:      75.0%
github.com/vaayne/anna/internal/channel/identity.go:53:      68.2%
github.com/vaayne/anna/internal/channel/linkcode.go:16:      81.2%
github.com/vaayne/anna/internal/channel/notifier.go:37:      100.0%
github.com/vaayne/anna/internal/channel/notifier.go:42:      100.0%
github.com/vaayne/anna/internal/channel/notifier.go:50:      100.0%
github.com/vaayne/anna/internal/channel/notifier.go:88:      100.0%
github.com/vaayne/anna/internal/channel/notify_tool.go:16:   100.0%
github.com/vaayne/anna/internal/channel/notify_tool.go:43:   100.0%
github.com/vaayne/anna/internal/channel/notify_tool.go:51:   100.0%
github.com/vaayne/anna/internal/channel/qq/handler.go:113:   30.0%
github.com/vaayne/anna/internal/channel/qq/handler.go:147:   100.0%
github.com/vaayne/anna/internal/channel/qq/handler.go:160:   76.2%
github.com/vaayne/anna/internal/channel/qq/handler.go:197:   0.0%
github.com/vaayne/anna/internal/channel/qq/handler.go:19:    0.0%
github.com/vaayne/anna/internal/channel/qq/handler.go:238:   69.2%
github.com/vaayne/anna/internal/channel/qq/handler.go:262:   100.0%
github.com/vaayne/anna/internal/channel/qq/handler.go:267:   0.0%
github.com/vaayne/anna/internal/channel/qq/handler.go:277:   0.0%
github.com/vaayne/anna/internal/channel/qq/handler.go:289:   0.0%
github.com/vaayne/anna/internal/channel/qq/handler.go:63:    0.0%
github.com/vaayne/anna/internal/channel/qq/model.go:11:      100.0%
github.com/vaayne/anna/internal/channel/qq/model.go:21:      90.9%
github.com/vaayne/anna/internal/channel/qq/model.go:43:      91.7%
github.com/vaayne/anna/internal/channel/qq/model.go:78:      100.0%
github.com/vaayne/anna/internal/channel/qq/qq.go:106:        0.0%
github.com/vaayne/anna/internal/channel/qq/qq.go:151:        100.0%
github.com/vaayne/anna/internal/channel/qq/qq.go:159:        100.0%
github.com/vaayne/anna/internal/channel/qq/qq.go:162:        18.2%
github.com/vaayne/anna/internal/channel/qq/qq.go:192:        100.0%
github.com/vaayne/anna/internal/channel/qq/qq.go:201:        100.0%
github.com/vaayne/anna/internal/channel/qq/qq.go:206:        100.0%
github.com/vaayne/anna/internal/channel/qq/qq.go:212:        0.0%
github.com/vaayne/anna/internal/channel/qq/qq.go:25:         100.0%
github.com/vaayne/anna/internal/channel/qq/qq.go:64:         0.0%
github.com/vaayne/anna/internal/channel/qq/qq.go:73:         90.9%
github.com/vaayne/anna/internal/channel/qq/render.go:11:     0.0%
github.com/vaayne/anna/internal/channel/qq/render.go:41:     100.0%
github.com/vaayne/anna/internal/channel/qq/stream.go:131:    0.0%
github.com/vaayne/anna/internal/channel/qq/stream.go:171:    78.6%
github.com/vaayne/anna/internal/channel/qq/stream.go:27:     100.0%
github.com/vaayne/anna/internal/channel/qq/stream.go:53:     0.0%
github.com/vaayne/anna/internal/channel/resolved.go:29:      0.0%
github.com/vaayne/anna/internal/channel/resolved.go:32:      0.0%
github.com/vaayne/anna/internal/channel/resolved.go:37:      0.0%
github.com/vaayne/anna/internal/channel/resolved.go:42:      0.0%
github.com/vaayne/anna/internal/channel/resolved.go:48:      0.0%
github.com/vaayne/anna/internal/channel/resolved.go:58:      0.0%
github.com/vaayne/anna/internal/channel/resolved.go:71:      0.0%
github.com/vaayne/anna/internal/channel/resolved.go:81:      0.0%
github.com/vaayne/anna/internal/channel/telegram/handler.go:109: 0.0%
github.com/vaayne/anna/internal/channel/telegram/handler.go:118: 0.0%
github.com/vaayne/anna/internal/channel/telegram/handler.go:137: 0.0%
github.com/vaayne/anna/internal/channel/telegram/handler.go:161: 0.0%
github.com/vaayne/anna/internal/channel/telegram/handler.go:194: 0.0%
github.com/vaayne/anna/internal/channel/telegram/handler.go:19: 100.0%
github.com/vaayne/anna/internal/channel/telegram/handler.go:239: 0.0%
github.com/vaayne/anna/internal/channel/telegram/handler.go:27: 100.0%
github.com/vaayne/anna/internal/channel/telegram/handler.go:38: 0.0%
github.com/vaayne/anna/internal/channel/telegram/handler.go:42: 0.0%
github.com/vaayne/anna/internal/channel/telegram/model.go:126: 0.0%
github.com/vaayne/anna/internal/channel/telegram/model.go:14: 0.0%
github.com/vaayne/anna/internal/channel/telegram/model.go:21: 0.0%
github.com/vaayne/anna/internal/channel/telegram/model.go:88: 0.0%
github.com/vaayne/anna/internal/channel/telegram/render.go:22: 0.0%
github.com/vaayne/anna/internal/channel/telegram/render.go:32: 0.0%
github.com/vaayne/anna/internal/channel/telegram/render.go:48: 0.0%
github.com/vaayne/anna/internal/channel/telegram/render.go:67: 85.7%
github.com/vaayne/anna/internal/channel/telegram/stream.go:110: 100.0%
github.com/vaayne/anna/internal/channel/telegram/stream.go:138: 100.0%
github.com/vaayne/anna/internal/channel/telegram/stream.go:146: 100.0%
github.com/vaayne/anna/internal/channel/telegram/stream.go:153: 100.0%
github.com/vaayne/anna/internal/channel/telegram/stream.go:215: 100.0%
github.com/vaayne/anna/internal/channel/telegram/stream.go:235: 100.0%
github.com/vaayne/anna/internal/channel/telegram/stream.go:244: 75.0%
github.com/vaayne/anna/internal/channel/telegram/stream.go:262: 0.0%
github.com/vaayne/anna/internal/channel/telegram/stream.go:281: 0.0%
github.com/vaayne/anna/internal/channel/telegram/stream.go:338: 0.0%
github.com/vaayne/anna/internal/channel/telegram/stream.go:408: 85.7%
github.com/vaayne/anna/internal/channel/telegram/stream.go:437: 0.0%
github.com/vaayne/anna/internal/channel/telegram/stream.go:448: 0.0%
github.com/vaayne/anna/internal/channel/telegram/stream.go:60: 100.0%
github.com/vaayne/anna/internal/channel/telegram/stream.go:77: 100.0%
github.com/vaayne/anna/internal/channel/telegram/stream.go:97: 83.3%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:107: 0.0%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:116: 0.0%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:136: 0.0%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:142: 0.0%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:145: 0.0%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:182: 100.0%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:185: 0.0%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:209: 0.0%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:221: 0.0%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:227: 0.0%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:240: 0.0%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:258: 0.0%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:267: 0.0%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:26: 0.0%
github.com/vaayne/anna/internal/channel/telegram/telegram.go:60: 0.0%
github.com/vaayne/anna/internal/channel/util.go:13:          100.0%
github.com/vaayne/anna/internal/channel/util.go:42:          100.0%
github.com/vaayne/anna/internal/config/config.go:37:         100.0%
github.com/vaayne/anna/internal/config/config.go:49:         100.0%
github.com/vaayne/anna/internal/config/config.go:54:         66.7%
github.com/vaayne/anna/internal/config/config.go:62:         80.0%
github.com/vaayne/anna/internal/config/config.go:73:         100.0%
github.com/vaayne/anna/internal/config/dbstore.go:107:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:115:       90.0%
github.com/vaayne/anna/internal/config/dbstore.go:141:       80.0%
github.com/vaayne/anna/internal/config/dbstore.go:167:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:173:       85.7%
github.com/vaayne/anna/internal/config/dbstore.go:185:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:193:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:207:       85.7%
github.com/vaayne/anna/internal/config/dbstore.go:219:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:21:        100.0%
github.com/vaayne/anna/internal/config/dbstore.go:227:       75.0%
github.com/vaayne/anna/internal/config/dbstore.go:239:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:248:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:259:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:267:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:276:       83.3%
github.com/vaayne/anna/internal/config/dbstore.go:28:        85.7%
github.com/vaayne/anna/internal/config/dbstore.go:290:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:298:       0.0%
github.com/vaayne/anna/internal/config/dbstore.go:315:       0.0%
github.com/vaayne/anna/internal/config/dbstore.go:324:       83.3%
github.com/vaayne/anna/internal/config/dbstore.go:335:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:344:       86.7%
github.com/vaayne/anna/internal/config/dbstore.go:40:        100.0%
github.com/vaayne/anna/internal/config/dbstore.go:423:       76.5%
github.com/vaayne/anna/internal/config/dbstore.go:467:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:478:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:489:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:497:       75.0%
github.com/vaayne/anna/internal/config/dbstore.go:516:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:51:        75.0%
github.com/vaayne/anna/internal/config/dbstore.go:532:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:540:       100.0%
github.com/vaayne/anna/internal/config/dbstore.go:64:        75.0%
github.com/vaayne/anna/internal/config/dbstore.go:77:        100.0%
github.com/vaayne/anna/internal/config/dbstore.go:83:        85.7%
github.com/vaayne/anna/internal/config/dbstore.go:95:        85.7%
github.com/vaayne/anna/internal/config/model.go:33:          87.5%
github.com/vaayne/anna/internal/config/models_cache.go:24:   0.0%
github.com/vaayne/anna/internal/config/models_cache.go:29:   0.0%
github.com/vaayne/anna/internal/config/models_cache.go:42:   0.0%
github.com/vaayne/anna/internal/config/paths.go:17:          100.0%
github.com/vaayne/anna/internal/config/paths.go:24:          60.0%
github.com/vaayne/anna/internal/config/paths.go:42:          100.0%
github.com/vaayne/anna/internal/config/paths.go:48:          100.0%
github.com/vaayne/anna/internal/config/paths.go:53:          100.0%
github.com/vaayne/anna/internal/config/snapshot.go:102:      0.0%
github.com/vaayne/anna/internal/config/snapshot.go:113:      100.0%
github.com/vaayne/anna/internal/config/snapshot.go:118:      100.0%
github.com/vaayne/anna/internal/config/snapshot.go:45:       100.0%
github.com/vaayne/anna/internal/config/snapshot.go:54:       100.0%
github.com/vaayne/anna/internal/config/snapshot.go:69:       100.0%
github.com/vaayne/anna/internal/config/snapshot.go:77:       87.5%
github.com/vaayne/anna/internal/db/database.go:112:          0.0%
github.com/vaayne/anna/internal/db/database.go:132:          0.0%
github.com/vaayne/anna/internal/db/database.go:18:           0.0%
github.com/vaayne/anna/internal/db/database.go:44:           0.0%
github.com/vaayne/anna/internal/db/database.go:57:           0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_identities.sql.go:25: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_identities.sql.go:48: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_identities.sql.go:57: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_identities.sql.go:80: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_identities.sql.go:98: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_policies.sql.go:136: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_policies.sql.go:196: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_policies.sql.go:31: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_policies.sql.go:65: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_policies.sql.go:74: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_policies.sql.go:97: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_roles.sql.go:115: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_roles.sql.go:25: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_roles.sql.go:47: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_roles.sql.go:56: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_roles.sql.go:73: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_sessions.sql.go:24: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_sessions.sql.go:40: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_sessions.sql.go:49: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_sessions.sql.go:58: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_sessions.sql.go:67: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_sessions.sql.go:88: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_user_agents.sql.go:23: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_user_agents.sql.go:32: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_user_agents.sql.go:59: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_user_agents.sql.go:91: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_user_roles.sql.go:110: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_user_roles.sql.go:23: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_user_roles.sql.go:35: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_user_roles.sql.go:72: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_users.sql.go:143: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_users.sql.go:16: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_users.sql.go:34: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_users.sql.go:52: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_users.sql.go:61: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_users.sql.go:79: 0.0%
github.com/vaayne/anna/internal/db/sqlc/auth_users.sql.go:97: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_agent_memory.sql.go:125: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_agent_memory.sql.go:21: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_agent_memory.sql.go:35: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_agent_memory.sql.go:51: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_agent_memory.sql.go:83: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_conversations.sql.go:113: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_conversations.sql.go:136: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_conversations.sql.go:175: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_conversations.sql.go:220: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_conversations.sql.go:234: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_conversations.sql.go:243: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_conversations.sql.go:24: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_conversations.sql.go:252: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_conversations.sql.go:266: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_conversations.sql.go:280: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_conversations.sql.go:59: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_conversations.sql.go:90: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_items.sql.go:127: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_items.sql.go:174: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_items.sql.go:193: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_items.sql.go:220: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_items.sql.go:26: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_items.sql.go:41: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_items.sql.go:57: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_items.sql.go:66: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_items.sql.go:79: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_messages.sql.go:101: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_messages.sql.go:121: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_messages.sql.go:132: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_messages.sql.go:170: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_messages.sql.go:218: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_messages.sql.go:262: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_messages.sql.go:29: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_messages.sql.go:307: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_messages.sql.go:70: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_messages.sql.go:90: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_summaries.sql.go:100: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_summaries.sql.go:140: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_summaries.sql.go:167: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_summaries.sql.go:210: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_summaries.sql.go:249: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_summaries.sql.go:296: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_summaries.sql.go:312: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_summaries.sql.go:32: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_summaries.sql.go:330: 0.0%
github.com/vaayne/anna/internal/db/sqlc/ctx_summaries.sql.go:53: 0.0%
github.com/vaayne/anna/internal/db/sqlc/db.go:19:            0.0%
github.com/vaayne/anna/internal/db/sqlc/db.go:27:            0.0%
github.com/vaayne/anna/internal/db/sqlc/sched_jobs.sql.go:100: 0.0%
github.com/vaayne/anna/internal/db/sqlc/sched_jobs.sql.go:155: 0.0%
github.com/vaayne/anna/internal/db/sqlc/sched_jobs.sql.go:33: 0.0%
github.com/vaayne/anna/internal/db/sqlc/sched_jobs.sql.go:68: 0.0%
github.com/vaayne/anna/internal/db/sqlc/sched_jobs.sql.go:77: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings.sql.go:16:  0.0%
github.com/vaayne/anna/internal/db/sqlc/settings.sql.go:25:  0.0%
github.com/vaayne/anna/internal/db/sqlc/settings.sql.go:36:  0.0%
github.com/vaayne/anna/internal/db/sqlc/settings.sql.go:72:  0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_agents.sql.go:134: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_agents.sql.go:195: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_agents.sql.go:30: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_agents.sql.go:63: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_agents.sql.go:72: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_agents.sql.go:95: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_channel_agents.sql.go:21: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_channel_agents.sql.go:35: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_channel_agents.sql.go:51: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_channel_agents.sql.go:93: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_channels.sql.go:16: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_channels.sql.go:33: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_channels.sql.go:77: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_providers.sql.go:121: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_providers.sql.go:25: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_providers.sql.go:48: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_providers.sql.go:57: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_providers.sql.go:75: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_users.sql.go:130: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_users.sql.go:150: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_users.sql.go:25: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_users.sql.go:44: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_users.sql.go:68: 0.0%
github.com/vaayne/anna/internal/db/sqlc/settings_users.sql.go:87: 0.0%
github.com/vaayne/anna/internal/embedded/embedded.go:105:    0.0%
github.com/vaayne/anna/internal/embedded/embedded.go:20:     100.0%
github.com/vaayne/anna/internal/embedded/embedded.go:29:     100.0%
github.com/vaayne/anna/internal/embedded/embedded.go:34:     0.0%
github.com/vaayne/anna/internal/embedded/embedded.go:43:     75.0%
github.com/vaayne/anna/internal/embedded/embedded.go:57:     58.8%
github.com/vaayne/anna/internal/embedded/embedded.go:91:     87.5%
github.com/vaayne/anna/internal/memory/assembler.go:100:     85.7%
github.com/vaayne/anna/internal/memory/assembler.go:113:     66.7%
github.com/vaayne/anna/internal/memory/assembler.go:147:     100.0%
github.com/vaayne/anna/internal/memory/assembler.go:182:     87.5%
github.com/vaayne/anna/internal/memory/assembler.go:19:      100.0%
github.com/vaayne/anna/internal/memory/assembler.go:26:      90.9%
github.com/vaayne/anna/internal/memory/assembler.go:83:      100.0%
github.com/vaayne/anna/internal/memory/compaction.go:125:    100.0%
github.com/vaayne/anna/internal/memory/compaction.go:156:    82.4%
github.com/vaayne/anna/internal/memory/compaction.go:24:     100.0%
github.com/vaayne/anna/internal/memory/compaction.go:271:    88.2%
github.com/vaayne/anna/internal/memory/compaction.go:312:    100.0%
github.com/vaayne/anna/internal/memory/compaction.go:350:    81.0%
github.com/vaayne/anna/internal/memory/compaction.go:37:     81.8%
github.com/vaayne/anna/internal/memory/compaction.go:476:    100.0%
github.com/vaayne/anna/internal/memory/compaction.go:78:     63.6%
github.com/vaayne/anna/internal/memory/compaction.go:98:     87.5%
github.com/vaayne/anna/internal/memory/context.go:14:        0.0%
github.com/vaayne/anna/internal/memory/context.go:19:        0.0%
github.com/vaayne/anna/internal/memory/context.go:25:        0.0%
github.com/vaayne/anna/internal/memory/context.go:30:        0.0%
github.com/vaayne/anna/internal/memory/context.go:36:        0.0%
github.com/vaayne/anna/internal/memory/context.go:41:        0.0%
github.com/vaayne/anna/internal/memory/engine.go:107:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:113:        80.0%
github.com/vaayne/anna/internal/memory/engine.go:124:        78.6%
github.com/vaayne/anna/internal/memory/engine.go:182:        75.0%
github.com/vaayne/anna/internal/memory/engine.go:191:        88.9%
github.com/vaayne/anna/internal/memory/engine.go:207:        85.7%
github.com/vaayne/anna/internal/memory/engine.go:220:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:226:        75.0%
github.com/vaayne/anna/internal/memory/engine.go:275:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:284:        90.9%
github.com/vaayne/anna/internal/memory/engine.go:304:        77.8%
github.com/vaayne/anna/internal/memory/engine.go:324:        66.7%
github.com/vaayne/anna/internal/memory/engine.go:331:        83.3%
github.com/vaayne/anna/internal/memory/engine.go:355:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:363:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:379:        75.0%
github.com/vaayne/anna/internal/memory/engine.go:406:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:414:        80.0%
github.com/vaayne/anna/internal/memory/engine.go:475:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:488:        83.3%
github.com/vaayne/anna/internal/memory/engine.go:510:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:531:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:54:         100.0%
github.com/vaayne/anna/internal/memory/engine.go:556:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:571:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:594:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:615:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:63:         100.0%
github.com/vaayne/anna/internal/memory/engine.go:650:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:660:        100.0%
github.com/vaayne/anna/internal/memory/engine.go:71:         83.3%
github.com/vaayne/anna/internal/memory/engine.go:85:         100.0%
github.com/vaayne/anna/internal/memory/retrieval.go:133:     92.6%
github.com/vaayne/anna/internal/memory/retrieval.go:14:      100.0%
github.com/vaayne/anna/internal/memory/retrieval.go:188:     100.0%
github.com/vaayne/anna/internal/memory/retrieval.go:197:     100.0%
github.com/vaayne/anna/internal/memory/retrieval.go:211:     100.0%
github.com/vaayne/anna/internal/memory/retrieval.go:27:      0.0%
github.com/vaayne/anna/internal/memory/retrieval.go:37:      86.4%
github.com/vaayne/anna/internal/memory/retrieval.go:94:      87.5%
github.com/vaayne/anna/internal/memory/summarize.go:127:     94.7%
github.com/vaayne/anna/internal/memory/summarize.go:164:     100.0%
github.com/vaayne/anna/internal/memory/summarize.go:193:     100.0%
github.com/vaayne/anna/internal/memory/summarize.go:96:      100.0%
github.com/vaayne/anna/internal/memory/tool/helpers.go:4:    71.4%
github.com/vaayne/anna/internal/memory/tool/memory.go:100:   88.2%
github.com/vaayne/anna/internal/memory/tool/memory.go:130:   80.0%
github.com/vaayne/anna/internal/memory/tool/memory.go:148:   81.8%
github.com/vaayne/anna/internal/memory/tool/memory.go:168:   85.7%
github.com/vaayne/anna/internal/memory/tool/memory.go:61:    100.0%
github.com/vaayne/anna/internal/memory/tool/memory.go:66:    100.0%
github.com/vaayne/anna/internal/memory/tool/memory.go:80:    100.0%
github.com/vaayne/anna/internal/memory/tool/memory.go:84:    100.0%
github.com/vaayne/anna/internal/memory/types.go:125:         100.0%
github.com/vaayne/anna/internal/memory/types.go:200:         100.0%
github.com/vaayne/anna/internal/memory/usermemory.go:16:     100.0%
github.com/vaayne/anna/internal/memory/usermemory.go:22:     75.0%
github.com/vaayne/anna/internal/memory/usermemory.go:31:     66.7%
github.com/vaayne/anna/internal/plugin/adapt.go:15:          100.0%
github.com/vaayne/anna/internal/plugin/adapt.go:23:          100.0%
github.com/vaayne/anna/internal/plugin/adapt.go:28:          100.0%
github.com/vaayne/anna/internal/plugin/convert.go:12:        43.8%
github.com/vaayne/anna/internal/plugin/convert.go:46:        85.7%
github.com/vaayne/anna/internal/plugin/convert.go:58:        71.4%
github.com/vaayne/anna/internal/plugin/hostapi.go:105:       92.3%
github.com/vaayne/anna/internal/plugin/hostapi.go:131:       37.5%
github.com/vaayne/anna/internal/plugin/hostapi.go:149:       100.0%
github.com/vaayne/anna/internal/plugin/hostapi.go:154:       50.9%
github.com/vaayne/anna/internal/plugin/hostapi.go:247:       0.0%
github.com/vaayne/anna/internal/plugin/hostapi.go:279:       0.0%
github.com/vaayne/anna/internal/plugin/hostapi.go:35:        55.0%
github.com/vaayne/anna/internal/plugin/manager.go:20:        100.0%
github.com/vaayne/anna/internal/plugin/manager.go:28:        0.0%
github.com/vaayne/anna/internal/plugin/manager.go:34:        83.3%
github.com/vaayne/anna/internal/plugin/manager.go:46:        66.7%
github.com/vaayne/anna/internal/plugin/manager.go:57:        0.0%
github.com/vaayne/anna/internal/plugin/manager.go:67:        100.0%
github.com/vaayne/anna/internal/plugin/manager.go:76:        100.0%
github.com/vaayne/anna/internal/plugin/registry.go:18:       100.0%
github.com/vaayne/anna/internal/plugin/registry.go:31:       100.0%
github.com/vaayne/anna/internal/plugin/registry.go:45:       100.0%
github.com/vaayne/anna/internal/plugin/registry.go:52:       100.0%
github.com/vaayne/anna/internal/plugin/registry.go:72:       100.0%
github.com/vaayne/anna/internal/plugin/runtime.go:207:       85.0%
github.com/vaayne/anna/internal/plugin/runtime.go:245:       100.0%
github.com/vaayne/anna/internal/plugin/runtime.go:24:        100.0%
github.com/vaayne/anna/internal/plugin/runtime.go:26:        100.0%
github.com/vaayne/anna/internal/plugin/runtime.go:40:        100.0%
github.com/vaayne/anna/internal/plugin/runtime.go:46:        84.3%
github.com/vaayne/anna/internal/scheduler/heartbeat.go:113:  75.0%
github.com/vaayne/anna/internal/scheduler/heartbeat.go:129:  80.0%
github.com/vaayne/anna/internal/scheduler/heartbeat.go:146:  80.0%
github.com/vaayne/anna/internal/scheduler/heartbeat.go:155:  90.9%
github.com/vaayne/anna/internal/scheduler/heartbeat.go:175:  71.4%
github.com/vaayne/anna/internal/scheduler/heartbeat.go:190:  100.0%
github.com/vaayne/anna/internal/scheduler/heartbeat.go:209:  100.0%
github.com/vaayne/anna/internal/scheduler/heartbeat.go:36:   100.0%
github.com/vaayne/anna/internal/scheduler/heartbeat.go:45:   0.0%
github.com/vaayne/anna/internal/scheduler/heartbeat.go:64:   83.9%
github.com/vaayne/anna/internal/scheduler/job.go:39:         85.7%
github.com/vaayne/anna/internal/scheduler/persistence.go:118: 71.4%
github.com/vaayne/anna/internal/scheduler/persistence.go:16: 85.7%
github.com/vaayne/anna/internal/scheduler/persistence.go:29: 100.0%
github.com/vaayne/anna/internal/scheduler/persistence.go:51: 100.0%
github.com/vaayne/anna/internal/scheduler/persistence.go:57: 71.9%
github.com/vaayne/anna/internal/scheduler/service.go:103:    100.0%
github.com/vaayne/anna/internal/scheduler/service.go:107:    88.0%
github.com/vaayne/anna/internal/scheduler/service.go:151:    60.0%
github.com/vaayne/anna/internal/scheduler/service.go:162:    0.0%
github.com/vaayne/anna/internal/scheduler/service.go:187:    87.8%
github.com/vaayne/anna/internal/scheduler/service.go:267:    84.6%
github.com/vaayne/anna/internal/scheduler/service.go:294:    100.0%
github.com/vaayne/anna/internal/scheduler/service.go:305:    88.9%
github.com/vaayne/anna/internal/scheduler/service.go:349:    88.9%
github.com/vaayne/anna/internal/scheduler/service.go:52:     75.0%
github.com/vaayne/anna/internal/scheduler/service.go:69:     0.0%
github.com/vaayne/anna/internal/scheduler/service.go:85:     100.0%
github.com/vaayne/anna/internal/scheduler/service.go:90:     100.0%
github.com/vaayne/anna/internal/scheduler/service.go:97:     100.0%
github.com/vaayne/anna/internal/scheduler/tool.go:113:       100.0%
github.com/vaayne/anna/internal/scheduler/tool.go:123:       83.3%
github.com/vaayne/anna/internal/scheduler/tool.go:62:        100.0%
github.com/vaayne/anna/internal/scheduler/tool.go:67:        100.0%
github.com/vaayne/anna/internal/scheduler/tool.go:76:        100.0%
github.com/vaayne/anna/internal/scheduler/tool.go:81:        100.0%
github.com/vaayne/anna/internal/scheduler/tool.go:95:        91.7%
github.com/vaayne/anna/internal/skills/install.go:22:        100.0%
github.com/vaayne/anna/internal/skills/install.go:26:        88.9%
github.com/vaayne/anna/internal/skills/install.go:43:        46.7%
github.com/vaayne/anna/internal/skills/install.go:77:        0.0%
github.com/vaayne/anna/internal/skills/install.go:98:        75.0%
github.com/vaayne/anna/internal/skills/list.go:17:           87.5%
github.com/vaayne/anna/internal/skills/load.go:10:           90.9%
github.com/vaayne/anna/internal/skills/remove.go:14:         66.7%
github.com/vaayne/anna/internal/skills/remove.go:34:         100.0%
github.com/vaayne/anna/internal/skills/tool.go:111:          23.1%
github.com/vaayne/anna/internal/skills/tool.go:56:           100.0%
github.com/vaayne/anna/internal/skills/tool.go:71:           100.0%
github.com/vaayne/anna/internal/skills/tool.go:79:           100.0%
github.com/vaayne/anna/internal/skills/tool.go:88:           100.0%
github.com/vaayne/anna/internal/skills/tool.go:93:           75.0%

vaayne added 10 commits March 20, 2026 22:57
…kage

- Remove `anna onboard` and `anna gateway` subcommands
- `anna` (bare) is now the default server action (admin panel + channels)
- Add `--open` flag to launch browser, `--admin-port` with PORT env support
- Default admin port: 25678
- Move `internal/auth/authdb/` → `internal/db/authstore.go`
- Rename mise tasks: `atlas:*` → `db:*`, remove redundant tasks
- Update all docs (en/zh/ja), builtin skill, README, CLAUDE.md
- Scheduler: users see/manage only their own jobs, admins see all and
  can create system jobs (user_id=0) that broadcast to everyone
- Sessions: non-admin users only see their own sessions
- Notifications: user-owned scheduler jobs notify only the owner via
  their linked channel identities; system jobs broadcast to all
- Add system:user-own-scheduler seed policy
- Open scheduler page/APIs to all authenticated users with handler-level
  RBAC instead of admin-only middleware
- Add NotifyUser to Dispatcher with graceful fallback to broadcast
- Add DELETE /api/auth/users/{id}/identities/{identityId} endpoint
- Add unlink button in user detail panel's identities section
- Allows admin to detach channel identities from users so they can be
  re-linked to different accounts
The admin panel and channel bots each created their own LinkCodeStore,
so link codes generated in the admin profile page were never found by
channel handlers. Pass the shared store into admin.New() instead.

Also fix click.away on user detail panel closing when confirm dialog
is open, causing "selectedUser is null" errors on identity unlink.
…nking

- Remove auto-migration in ResolveUserWithAuth — unlinked channel users
  now get settings_users only (no auth user created automatically)
- Change link code format from bare code to "/link <code>" command
  (bare codes still accepted for backward compat)
- Improve error messages for expired/wrong-platform/already-linked cases
- Update profile page: show "/link <code>" with copy button
- Remove dead randomPassword helper
ResolvedChat.UserID() now prefers AuthUserID (auth_users.id) over
User.ID (settings_users.id). This ensures sessions and per-user memory
are scoped to the correct auth user after identity re-linking.
The user_id column now stores auth_users.id for RBAC users but
settings_users.id for legacy CLI users. Drop the FK constraint
to support both ID spaces.
The session detail page was looking up user name via config.Store.GetUser
(settings_users table) but the user_id in sessions is now auth_users.id.
Switch to authStore.GetUser to show the correct username.
Drop settings_users table entirely. auth_users now has default_agent_id
and is the single user table. Key changes:

- auth.AuthUser gains DefaultAgentID field
- auth.AuthStore gains UpdateUserDefaultAgent method
- config.Store loses User type and all user methods
- channel.ResolveUser now takes authStore only (no config.Store)
- channel.ResolvedIdentity uses auth.AuthUser directly
- channel.ResolvedChat carries single User field (no dual ID)
- channel.ResolveAgent unified (no separate WithAuth variant)
- Channel bots use single Resolve path
- Admin /api/users legacy endpoints removed
- All tests updated
@vaayne
Copy link
Owner Author

vaayne commented Mar 21, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 68e47ec05e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +16 to +17
-- Copy rows from old table "auth_users" to new temporary table "new_auth_users"
INSERT INTO `new_auth_users` (`id`, `username`, `password_hash`, `is_active`, `created_at`, `updated_at`) SELECT `id`, `username`, IFNULL(`password_hash`, '') AS `password_hash`, `is_active`, `created_at`, `updated_at` FROM `auth_users`;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Backfill legacy settings_users before rebuilding auth_users

On upgrades from the pre-auth schema, this migration repopulates new_auth_users only from the transient auth_users table and never carries over the existing settings_users rows that owned default_agent_id and ctx_agent_memory. Because the earlier fix_memory_user_fk migration intentionally leaves memories keyed by raw user_id, newly registered auth users can collide with those legacy IDs and inherit another user's memory/default-agent state, while the original channel users lose access entirely. This needs to migrate settings_users into auth_users/auth_identities before the drop.

Useful? React with 👍 / 👎.

Comment on lines +36 to +39
identity, err := authStore.GetIdentityByPlatform(ctx, platform, externalID)
if err != nil {
return config.User{}, fmt.Errorf("resolve user: %w", err)
log.Debug("no linked identity found, user must link via link code")
return ResolvedIdentity{}, nil

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fail closed on channel identity lookup errors

This treats every GetIdentityByPlatform failure as 'unlinked user'. If SQLite returns a real error here (for example a locked database or schema problem), ResolveAgent later sees identity.User.ID == 0 and skips RBAC entirely, routing the message as an unrestricted guest. The GetUser fallback a few lines below has the same fail-open behavior, so only not-found errors should be downgraded to an anonymous identity.

Useful? React with 👍 / 👎.

async loadLegacyUsers() {
if (this.legacyUsers.length > 0) return // already loaded
try {
const list = await api('GET', '/api/users') || []

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update the Memory tab to use the renamed user APIs

The retained legacy-memory UI still calls GET /api/users, but internal/admin/server.go in this commit no longer registers that route and only keeps /api/users/{id}/default-agent plus the memory endpoints. As soon as an admin opens the Memory tab, the initial load 404s, so the old per-user memory/default-agent editor is no longer usable on upgraded instances.

Useful? React with 👍 / 👎.

vaayne added 9 commits March 21, 2026 11:33
- Fail closed on DB errors in ResolveUser — only treat sql.ErrNoRows
  as "unlinked user", propagate real DB errors instead of silently
  falling back to anonymous identity
- Fix agent user assignment picker: load from /api/auth/users instead
  of removed /api/users (settings_users)
- Fix memory tab: load from /api/auth/users, map username field
Drop auth_roles and auth_user_roles tables. Each user now has a single
role column (TEXT, default 'user'). No per-request ListUserRoles query.

- AuthUser gains Role field, IsAdmin() helper
- AuthStore: remove role CRUD (CreateRole, ListRoles, etc.)
- AuthStore: add UpdateUserRole(userID, role)
- Middleware: read role from user row directly (no join query)
- Seed: SeedRolesAndPolicies renamed to SeedPolicies (no role table)
- Admin UI: single role badge, promote/demote buttons
- Policy engine unchanged (subjects.roles still works as []string)
- -621 lines net deletion
Linked auth users in private chats now share a single session across all
channels (Telegram, QQ, Feishu). Session key uses auth user ID instead
of platform-specific external ID. Group chats remain platform-specific.
…contrast

- Merge "Linked Identities" and "Link New Identity" into one section
- Hide link buttons for platforms already linked
- Replace alert-info with neutral alert for better link code readability
- Add isLinked() helper to profile JS
Users can now view, edit, and delete their own per-agent memories from
the profile page. Previously only admins could manage user memories.
New profile API endpoints scoped to the authenticated user.
Memory is per-agent, so it belongs on the agent page. Each agent row now
has a "My Memory" toggle that loads/saves the current user's memory for
that agent. Profile page no longer shows memory section.
…eation

- Add creator_id column to settings_agents (migration)
- Auto-generate agent ID from name (slugify with dedup)
- Remove ID and workspace fields from create form
- Non-admin users: scope forced to restricted, auto-assigned
- Admin-only scope selector, creator or admin can edit/delete
- Open POST/PUT/DELETE /api/agents to all auth users (with access checks)
- Update all agent tests for auto-generated IDs
@vaayne vaayne merged commit c3818ac into main Mar 21, 2026
4 of 6 checks passed
@vaayne vaayne deleted the feat/rbac branch March 21, 2026 15:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant