DnD Story logo

Technical Site Rules

Public reference for site-wide technical behavior that is not game mechanics or visual style. This page documents auth, permissions, ownership, admin gating, and billing policy.

Authentication + Session Model

Sign-in is handled through NextAuth with Google provider and JWT sessions. The app treats invalid or stale JWT cookies as signed out and continues safely.

  • Protected write actions use authenticated helpers (`requireCurrentUser` or `requireAdminUser`).
  • Many create/edit pages redirect signed-out users to the sign-in route with callback URLs.
  • Read routes can be public depending on visibility and ownership rules described below.

User Role + Plan Rules

Users are created from active sessions and assigned role/plan values used throughout permissions and billing logic.

RuleCurrent Behavior
Role assignment`admin` if email is in configured admin list, otherwise `user`.
Plan assignment`admin` users are `paid`; non-admin users default to `free`.
User record lifecycleCreated or updated during authenticated access with profile and credit fields.

Visibility + Ownership Rules

Visibility is normalized to `public` unless explicitly set to `private`. Private creation is restricted by plan/role.

  • `resolveRequestedVisibility` forces visibility to public when a user is not eligible for private content.
  • `canViewResource` allows public reads for everyone; private reads are owner/admin only.
  • `canEditResource` allows edits for owner/admin only.
ActionSigned OutSigned-in UserOwnerAdmin
View public resourceAllowedAllowedAllowedAllowed
View private resourceDeniedDenied unless ownerAllowedAllowed
Edit resourceDeniedDenied unless ownerAllowedAllowed
Create private resourceDeniedAllowed only for paid planAllowed only for paid planAllowed

Admin-Gated Functionality

Admin-only flows are explicitly guarded. Non-admin users are denied access even when signed in.

  • The admin page requires admin status and redirects non-admin users.
  • Admin API routes (credits and admin image operations) require `requireAdminUser`.
  • The Admin navigation link is shown only when the current user is admin.

Billing Policy Behavior

Credits are tracked in milli-cents. Daily refill uses credit profiles (`base`, `friends`, `family`) with Pacific midnight refresh, and ledger entries record all charge/refund/grant/top-up/promo events.

  • Profile refill runs once per Pacific date and only adds credits when balance is below that profile's cap.
  • Balances above cap are preserved; refill resumes only after spending below cap.
  • Charges require sufficient balance; insufficient credits return payment-required behavior.
  • Refunds, admin grants, promo redemption, and purchase top-ups update both user balance and ledger.
Ledger ReasonMeaning
image_generateCredits spent for image generation requests.
image_editCredits spent for image edit or adjust requests.
daily_refreshPacific-time daily refill added when user balance is below the profile cap.
image_refundCredits returned when image operation fails after charging.
admin_grantAdmin manually adds credits to a user account.
purchase_topupCredits added from a successful Stripe top-up purchase.
promo_bonusCredits added from promo code redemption.
profile_overrideAdmin changed a user credit profile.
promo_profile_grantPromo code granted or changed a user credit profile.

Do / Don't

Do

  • Use shared helpers (`canViewResource`, `canEditResource`, `resolveRequestedVisibility`) for access checks.
  • Gate admin-only operations with `requireAdminUser`.
  • Keep write endpoints authenticated with `requireCurrentUser` where appropriate.
  • Record billing-impacting actions through the credit ledger workflow.

Don't

  • Do not bypass shared permission helpers with ad-hoc ownership checks.
  • Do not assume signed-in users can create private content.
  • Do not expose admin actions in UI flows that lack server-side admin enforcement.
  • Do not change billing behavior without updating this public technical reference.