Roles & The Permission Model
Fyndow is a professional community and marketplace where local service providers are found, booked, and paid. Because the same platform serves the people who buy work, the people who sell it, the organizations that run communities, and the staff who keep the platform safe, every meaningful action on Fyndow is gated by a role. This chapter explains the four roles, how they are enforced, and the one structural rule that shapes the whole provider experience: a provider can own many businesses.
The Four Roles
A user's role is stored on their account record and travels with every authenticated session. The set of roles is fixed: provider, customer, organization, and admin.
| Role | What they do |
|---|---|
| Customer | Search providers, book services, buy products, pay invoices and bookings, leave reviews, and participate in forums. This is the default role for a new sign-up. |
| Provider | Create and manage one or more businesses, list services and products, manage a calendar, send quotes and invoices, receive payments, and participate in forums. |
| Organization | Create and manage gated forums (communities), publish targeted content to subscribers, and run community programs. Organizations do not get the business toolkit. |
| Admin | Verify credentials, resolve disputes, moderate forums, manage platform settings, and view platform analytics. Admin accounts are provisioned internally, not through public sign-up. |
A customer can be promoted to a provider through a role-upgrade flow (the "become a provider" path) without creating a new account — the platform flips the role and walks the user through slim onboarding (business name and city).
How the Role Is Enforced
Fyndow's backend is a headless API. Authentication is handled by a session-based authentication system, which issues a session stored in an httpOnly cookie (and a bearer token for the mobile app). The session payload is deliberately minimal:
{ userId, role, email, businessId? }
Because the role travels on the session, role checks require no extra database lookup. Two pieces work together on every request:
- The authentication layer extracts and validates the session.
- The role check reads the required-roles declaration on an endpoint and confirms the session's role is allowed.
function isAllowed(request):
requiredRoles = rolesDeclaredOn(request.endpoint)
if no requiredRoles: return true # endpoint open to any authenticated user
return requiredRoles.includes(request.session.role)
Both checks run globally. Every route is protected by default; an endpoint must explicitly opt out to be public (for example, viewing a public business page or running a search without logging in). There are no accidentally-open routes.
Role is necessary, not sufficient
Passing the role check only proves what kind of user you are. It does not prove you own the specific record you are touching. A second layer — ownership checks inside the service — guarantees that a provider can only edit their business, a customer can only read their bookings, and a provider's client list is scoped strictly to clients they have actually interacted with. The full request journey is:
Role tells the system who is asking; the service layer decides whether this particular thing is theirs.
The Access Control Matrix
The table below summarizes who can do what across the core domains. "own" means the records belonging to that user (or to a business they own).
| Domain | Customer | Provider | Organization | Admin |
|---|---|---|---|---|
| users | read/update self | read/update self | read/update self | CRUD all |
| businesses | read all | CRUD own (multiple) | read all | CRUD all |
| services | read active | CRUD own business(es) | read active | CRUD all |
| products | read active | CRUD own business | read active | CRUD all |
| bookings | CRUD own | CRUD own | — | CRUD all |
| quotes | read/accept/decline own | CRUD own business | — | CRUD all |
| invoices | read own | CRUD own business | — | CRUD all |
| orders | CRUD own | read own business | — | CRUD all |
| payments / transactions | read own | read own | — | read all |
| forums | read | read | CRUD own gated | CRUD |
| posts / comments | read, create | read, create, update own | create in own forums | CRUD + moderate |
| credentials | — | CRUD own business | — | CRUD + verify |
| reviews | create (completed txn), read | read, respond own | read | CRUD |
| announcements | read targeted | read targeted | CRUD (own forum subscribers) | CRUD |
Two patterns stand out. Customers can read every business and every active service or product (the marketplace is public by design), but they can only write their own bookings, orders, and reviews. Providers get full create/read/update/delete over the records of the businesses they own, but only read access to their own payments and transactions — money movement is created by the system in response to verified payment events, never by a hand-edit. Immutable financial records are covered in Payments & Payout Timing.
Multi-Business Ownership
The single most important structural decision in Fyndow's data model is that a provider can own many businesses from one account. A business's owner reference is not unique — one account can be the owner of any number of businesses.
Business record (conceptual):
id — unique identifier
ownerId — references the owning account (NOT unique → many businesses per owner)
name
slug — unique public handle
...
Each business is a fully independent unit. It has its own:
- public storefront page and unique
slug, - services, products, and portfolio,
- client list, bookings, quotes, and invoices,
- availability configuration and financials,
- credentials and community memberships.
In the apps, the provider sees a business selector to switch context. Under the hood, every business-scoped endpoint (services, scheduling, bookings, invoices, clients) accepts a businessId so the API returns only the records for the active business. A provider's full list of businesses is available via GET /businesses/mine/all.
This is why role alone is not enough: two providers are both "providers," but the service layer must still confirm that this businessId belongs to this ownerId before allowing a write. Multi-business management is described from the product side in The Business Toolkit.
Where Roles Meet the Rest of the Product
- The business toolkit (scheduling, quoting, invoicing, payments, clients, messaging) is provider-only. See The Business Toolkit.
- The AI assistant is the provider's primary interface and runs as that provider, scoped to the active business. See The AI Assistant.
- Gated communities are created and moderated by organizations and admins. See Communities & Forums.
- Credential verification is performed by admins; the resulting badges are public. See Trust & Reputation.
:::note TODO
The organization role is defined in the schema and access matrix, but the depth of its dedicated tooling (beyond gated-forum ownership and targeted announcements) is still being built out. Treat organization capabilities as the forum-ownership surface plus announcements until the organizations module is documented in How It Works.
:::