Dosu LogoDosu Logo
Ask
Join our Discord
Organization avatar
Mag StackerPublic
EvilBit Labs LLC
DocumentsMag Stacker
0008-magpul-mode-better-auth-additional-field
0008-magpul-mode-better-auth-additional-field
Type
External
Status
Published
Created
Jul 4, 2026
Updated
Jul 4, 2026
Source
docs/adr/0008-magpul-mode-better-auth-additional-field.md

ADR-0008: Store magpulMode as a Better Auth additionalFields flag on user#

Date: 2026-07-01
Status: accepted
Deciders: unclesp1d3r (with Claude Code)

Context#

The opt-in Magpul mode (ADR-0007, issue #21) needs a per-account boolean. The app had no user-preferences store, and the user table is Better Auth-managed — the admin plugin already added custom columns (role, banned, …). This is the app's first per-account profile setting.

Decision#

Store magpulMode as a Better Auth additionalFields boolean on user (default false, input: false), generated via the Better Auth CLI (magpul_mode) and surfaced on SessionUser. The settings toggle writes it with a scoped Drizzle update, because input: false blocks the client-facing updateUser path.

Alternatives Considered#

Alternative 1: Separate owner-scoped user_settings table#

  • Pros: clean separation; scales cleanly to many preferences.
  • Cons: a join and an entire table for one boolean; extra migration + maintenance surface.
  • Why not: YAGNI for a single flag. Revisit when a second per-account setting appears.

Alternative 2: Client-writable additionalField (input: true)#

  • Pros: the toggle could use Better Auth's updateUser directly, no Drizzle special-case.
  • Cons: exposes the flag to any client through a generic profile-update endpoint.
  • Why not: keep the server the sole writer; the settings action writes via a scoped Drizzle update instead.

Consequences#

Positive#

  • Rides the session for the common self-edit path — no extra query to know the acting user's mode.
  • Reuses the proven admin-plugin additionalFields pattern; a one-column migration.

Negative#

  • additionalFields are dynamically typed on the session, so getCurrentUser reads them via an explicitly-optional raw type and defaults to false (avoiding an unsound cast).
  • The settings write bypasses updateUser (uses Drizzle) — a small, documented special case in the server action.

Risks#

  • Accreting more booleans on user would erode cohesion; when a second per-account setting arrives, reconsider a dedicated settings table (noted for revisit).
Documents
Untitled
0004-join-ordinal-for-deterministic-csv-order
0007-magpul-constraint-domain-layer-not-db
0008-magpul-mode-better-auth-additional-field
0009-org-plugin-hybrid-sharing
0010-defer-typescript-6-upgrade
2026-06-30-001-test-playwright-e2e-suite-plan
2026-07-01-001-feat-magpul-mode-label-constraint-plan
2026-07-01-002-feat-firearms-taxonomy-plan
2026-07-02-001-feat-firearm-nickname-plan
2026-07-03-001-feat-shot-count-tracking-plan
2026-07-03-002-feat-magazine-label-prefix-numbering-plan
2026-07-04-001-feat-firearm-magazine-detail-view-plan
2026-07-04-002-feat-data-table-view-controls-plan
2026-07-05-001-refactor-remove-shadcn-token-bridge-plan
2026-07-06-001-feat-inventory-log-plan
2026-07-06-002-feat-ammo-inventory-plan
2026-07-07-001-feat-accessories-tracker-plan
2026-07-09-001-feat-firearm-photo-management-plan
2026-07-11-001-feat-firearm-documents-plan
2026-07-12-001-feat-encryption-at-rest-backups-plan
2026-07-13-001-feat-magazine-last-inventoried-plan
2026-07-15-001-feat-structured-logging-plan
7-add-ammo-inventory-tracking-with-low-stock-alerts-and-summary-rollups
AGENTS
AI_POLICY
CLAUDE
CONCEPTS
CONTRIBUTING
DESIGN
FAQ
Firearm isMagazineFed Flag Reference
Getting Started Guide
Getting Started for Clubs and Ranges
Getting Started for Individuals
Glossary
How-To Guide
Integration Guide
Migration Guide
PRODUCT
README
README
README
RELEASE
Runbook
SKILL
STRATEGY
Troubleshooting Guide
bun-test-misloads-playwright-e2e-specs
deployment
e2e-dotenv-mise-clobbers-launcher-env
encryption-at-rest
num-helper-coerces-nan-to-zero-bypassing-ammo-validation
pino-worker-transport-flush-bun-cli-exit-code
prefix-collision-safe-token-renaming
sodium-native-nextjs16-serverexternalpackages
tanstack-autoreset-render-loop-unstable-data
template
timezone-fragile-date-boundary-tests