Koovira Dev Docs
10-actors/permissions-matrix.md

Permissions & Authorization

Status: ๐ŸŸก gates validated; fine-grained CRUD matrix to be validated against authz code ยท Last validated: 2026-09-06

"Who can do what, under which conditions." Authorization in Koovira is layered gates, not a single ACL. Documented here are the gates confirmed against code + DB; the per-action CRUD matrix is seeded and marked where it still needs an authz-code pass.


The gate layers (in order)

  1. Authenticated? a valid kv_auth_sessions row (actor_type/actor_id). Guests get public

read only. See ../30-core/auth.md.

  1. Actor type โ€” the session's actor_type (customer / merchant / partner / padmin) + actor_role.
  2. Module on + visible โ€” kv_module_control flags (customer_access, merchant_enrollment,

frontend_visibility). See ../00-architecture/module-registry.md.

  1. Enrollment โ€” for merchant actions, a kv_module_registry type + company_master +

company_business_profiles row for that module.

  1. Membership tier โ€” kv_memberships gates limits/features (and platform fee %).
  2. KYC/verification โ€” approved claim_kyc_requests for KYC-gated publish/transact.
  3. Ownership โ€” the row's buyer_id/seller_id/company_id/createdby must match the actor

(e.g. getListing(viewerUserId, โ€ฆ), cancelOrderByUser(userId, โ€ฆ) all take the actor id and enforce ownership in the query).

  1. Staff permission โ€” sub-users get scoped rights via AdminUserManagerModule / merchant staff

screens (restaurant_staff, hotel_staff_assignments, etc.).

  1. Admin authz โ€” padmin has its own shell (padmin/includes/authz_ext.php โ€” corrected

2026-09-06, was cited as padmin/authz_ext.php; the file lives under includes/ and is require_once'd from padmin/includes/boot.php:55) + the 74-control (corrected 2026-09-06, was cited as 72; live count via SecurityControls::catalog()) SecurityControls switchboard (classs/admin/SecurityControls.php).

A request must clear every applicable layer. The Error Center's "merchant cannot publish" walkthrough is exactly this chain failing at layer 4/5/6.

Actor capability matrix (intended model โ€” verify each cell against the owning method)

CapabilityGuestCustomerMerchant ownerMerchant staffPartner (driver/rider/agent)Admin
View public contentโœ”โœ”โœ”โœ”โœ”โœ”
Buy / book (wallet)โœ–โœ”โœ”scopedโœ–โœ–
Create listing/productโœ–โœ–โœ”scopedโœ–โœ”
Publish (needs KYC)โœ–โœ–โœ” (KYC)scopedโœ–โœ”
Manage orders/fulfilโœ–own onlyโœ”scopedassignedโœ”
Financial (wallet/settlement)โœ–own walletcompanyscopedpayoutsall
Approve KYC / refunds / configโœ–โœ–โœ–โœ–โœ–โœ”
โœ”/โœ– reflect the layered gates above. Each cell becomes authoritative only when tied to the actual permission check in the owning method (most classs/*Module methods take the actor id and enforce ownership/role inline). Do not quote a cell as fact until that method is cited โ€” this is the next validation pass (read AdminUserManagerModule, padmin/authz_ext.php, and the staff-permission storage).

Business rules

  • BR-AUTHZ-001 โ€” every state-changing method takes the actor id and enforces ownership/role inline;

there is no trust of client-supplied owner ids (cf. CommerceX server-side pricing).

  • BR-AUTHZ-002 โ€” admin (padmin) is a separate actor domain with its own session shell + SecurityControls.
  • BR-AUTHZ-003 โ€” one account owns one company (house rule) โ€” block a 2nd company at every entry point.

To validate next

Read classs/AdminUserManagerModule.php + merchant staff-permission storage + padmin/authz_ext.php to turn the matrix cells into cited, per-action rules.