AstroBaaS

Customers & accounts

Admin User Management

Free — GPL coresize Mplanned, not built

Generated from docs/plan/core/admin-user-management/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.

Admin User Management lets merchants invite staff members, assign them roles, and revoke access without sharing passwords or API keys.

The problem

Merchants can’t add team members to their store; everything happens through a single admin account.

What it does

  • Invite staff by email (invite_links generates link)
  • List active staff members with role and email
  • Assign role to a user (Admin, Editor, Viewer, Fulfillment)
  • Disable/remove staff without deleting audit trail
  • View staff profile: email, role, last login, date added
  • Bulk disable team members (CSV import)
  • Role templates: pre-defined permission sets
  • Change user password (staff self-service via forgot-password)
  • Only store owner can add/remove Admin-level users

What it deliberately does NOT do

Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.

  • LDAP/SSO integration (requires external identity provider) — email-based invites only
  • Granular field-level permissions (e.g., can edit price but not inventory) — roles are coarse-grained
  • Delegation of invite approval — invites are immediate
  • User groups (e.g., shipping team) — flat structure
  • Real-time activity dashboard per user (covered by admin-activity-log) — user CRUD only

Data model

StoreUser: id, store_id, email, role_id, is_active, invited_at, accepted_at, last_login_at, created_by. Role: id, name, permissions (JSON array), store_id. Migration: add store_users and roles tables with seed data.

API

  • POST /admin/team
  • GET /admin/team
  • PATCH /admin/team/{user_id}
  • DELETE /admin/team/{user_id}
  • GET /admin/roles
  • POST /admin/roles
  • PATCH /admin/roles/{role_id}

Every route added here must also appear in src/pages/openapi.json.ts — a test fails the build if it does not.

Admin

Team members page: table of email, role, last login, added date; invite button. Invite form: email, role selector. Role management page: list roles, edit permissions, create custom role. Staff profile: email, role, date added, last login, disable option.

The seam — why this is core

Core owns: StoreUser table, Role definitions, permission checking middleware, invite/accept flow, password reset. Paid module owns: nothing; core infrastructure.

Core owns the interface + honest user manager; team management is infrastructure, not a per-country obligation or support commitment.

Dependencies

  • invite-links

Acceptance checks

Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.

  • Inviting staff sends them email with link (valid 7 days)
  • Setting user role to Editor restricts from viewing refund details
  • Disabling user logs them out; they cannot log in
  • User with Viewer role attempts PATCH on product; returns 403
  • Bulk-disabling 50 users via CSV takes < 2 seconds
  • Deleting user from DB does NOT remove name from audit logs

Risks

Permission checks bypassed if middleware misconfigured. Circular role inheritance. Owner disables own account. CSV import with bad role_id causes silent failures. Bulk operations not transactional.

Commercial context

Suggested pricefree (core)
Rival anchorShopify: included; Magento: included

The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.


Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full catalogue and ../../AI-GUIDE.md for how to work on this repository.