Skip to content

Auth Permission Model

simitben edited this page Apr 10, 2026 · 1 revision

Purpose

Define a stable permission model for API V3 that scales without coupling authorization to raw URLs.

Scope Status

  • This page is a design specification for upcoming auth hardening.

Recommended Model

Use resource-action permission codes and map routes to permission codes.

  • Permission code format: <module>.<resource>.<action>
  • Examples:
    • inventory.items.read
    • inventory.items.write
    • bpartner.master.read
    • sales.orders.create
    • accounting.journal-entries.void

Why Resource-Action (Instead of Raw Endpoint Path)

  • Path can change (/api/v3/...) while business permission remains the same.
  • Multiple endpoints can share one business permission.
  • Cleaner policy review for security/audit teams.
  • Easier module expansion without rewriting permission logic.

Permission Data Components

Table Role
system_api3_permission Master catalog of permission codes
system_api3_route_permission Route key/method/path -> permission mapping
system_api3_app_permission Granted permissions per app

Route Mapping Strategy

Each route registration should include a route key.

Example (target pattern):

$router->add('GET', '/api/v3/business-partners', [$controller, 'index'], true, [
    'route_key' => 'bpartner.list',
    'permission_code' => 'bpartner.master.read'
]);

If Router is not yet extended for metadata, maintain a centralized in-memory map inside Auth module as a transition step and move to route metadata in phase 2.

Module Permission Baseline (Seed Suggestion)

Module Resource Suggested Actions
bpartner master read, create, update
inventory items read, create, update
sales orders / invoices / receipts read, create, update, void
purchase invoices / vouchers read, create, update, void
accounting journal-entries / receipts / reports read, create, update, void, report
auth-admin apps / permissions / org-access read, create, update, revoke, rotate-secret

Evaluation Algorithm (Per Request)

  1. Resolve route_key + http_method.
  2. Find required permission_code from route mapping.
  3. Verify app has active grant in system_api3_app_permission.
  4. If missing, return 403 V3_AUTH_PERMISSION_DENIED.

Organization Access Coupling

Permission pass is not enough. Organization access must also pass:

  • Resolve effective organization from request (organization_id/org_id or organization_code/org_code).
  • Validate organization is in system_api3_app_organization for current app.
  • If missing, return 403 V3_AUTH_ORG_DENIED.

Permission Inspection Endpoint Output Shape

Suggested output from GET /api/v3/auth/me/permissions:

  • app_id
  • app_code
  • permissions[]:
    • permission_code
    • module_code
    • resource_code
    • action_code
  • allowed_organizations[]:
    • organization_id
    • organization_code

Migration Guidance

  • Do not infer permissions from old module/action names at runtime.
  • Build explicit mapping once, store in permission tables, and audit changes through admin endpoints.
  • Keep one source of truth in DB; avoid hardcoded permission checks inside controllers.

Clone this wiki locally