AstroBaaS

Customers & accounts

Role-Based Access Control

Free — GPL coresize Mplanned, not built

Generated from docs/plan/core/role-based-access-control/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.

Role-Based Access Control (RBAC) enforces permissions based on staff roles, letting merchants grant only the access each team member needs.

The problem

Merchants can’t trust employees with full access; they need to limit who can see orders, refunds, or edit prices.

What it does

  • Pre-defined roles: Admin, Editor, Viewer, Fulfillment
  • Custom roles with cherry-picked permissions
  • Permission checks on every API endpoint (middleware)
  • Audit trail logs user role at time of action
  • Deny access to protected endpoints for unauthorized roles
  • Settings for default role on new user invite
  • Dashboard: permission matrix showing who can do what

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.

  • Attribute-based access control (ABAC; conditional logic) — role-based only
  • Time-based access (9am-5pm only) — temporal rules out of scope
  • IP-based restrictions — belongs in security-hardening paid pack
  • Delegation — flat hierarchy
  • API key scoping per role (API keys are global) — keys separate from staff roles

Data model

Role: id, name, store_id, permissions (JSON array: orders.read, orders.write, products.read, etc.), is_default, created_at. No new migration; uses Role table from admin-user-management.

API

  • GET /admin/roles
  • POST /admin/roles
  • PATCH /admin/roles/{role_id}
  • DELETE /admin/roles/{role_id}
  • GET /admin/permissions

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

Admin

Permission matrix UI: rows = roles, columns = permissions, checkboxes to toggle. Role editor: pick-list of permissions. Staff assignment: show role description and affected permissions. Audit link: click role to see recent changes by users with that role.

The seam — why this is core

Core owns: permission list definition, permission-check middleware on every endpoint, enforcement at route level. Paid module owns: nothing; core infrastructure.

Core owns the interface + honest permission mapper; role management is infrastructure, not a credential or support commitment.

Dependencies

  • admin-user-management

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.

  • User with Viewer role attempts GET /admin/orders; response 200 OK
  • Same user attempts PATCH /admin/orders/{id}; response 403
  • Custom role InventoryOnly with [inventory.read, inventory.write] assigned; user cannot see orders (returns 403)
  • Deleting built-in role returns 400 Bad Request
  • Updating role to remove orders.read; user with that role loses order access immediately
  • Audit log shows staff role at time of action

Risks

Permission list bloat; every new endpoint needs permission string. Cached permissions from old role used. Default role set to Admin gives full access on invite. Permission denial marks past actions as unauthorized. SQL injection if not parameterized.

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.