# System Architecture

## Three interfaces, one core platform

```
                    PUBLIC WEBSITE (app/Controllers/Site)
                               |
                    CORE PLATFORM (shared DB, Users, Roles,
                    Permissions, Notifications, Documents,
                    Audit Logs — no per-interface duplication)
                               |
        -----------------------------------------------
        |                     |                       |
  MEMBER PORTAL           ADMIN / ERP                 API
  app/Controllers/Portal  app/Controllers/Adm    app/Controllers/Api
  (filter: auth:member)   (filter: auth:admin,   (filter: api token)
                           role:*)
```

## Membership vs. Role (kept as two separate concepts — spec section 7)

- **Membership category** (Pioneer / Prime / General, admin-configurable,
  not hard-coded) describes a person's *relationship to the development*.
- **Organizational role** (Super Admin, Finance Manager, Project Manager,
  Property Manager, Sales Manager, Content Manager, HR Manager,
  Procurement Officer, Agent, Staff, Member, ...) describes *what they are
  allowed to do in the system*.

A `users` row never merges these. `membership_id` and `role_id` (or a
`user_roles` pivot, for multi-role support) are independent foreign keys.

## RBAC

Permissions (`view`, `create`, `edit`, `delete`, `approve`, `publish`,
`export`, `print`, `manage`, `assign`) are assigned to **roles**, not
hard-coded per page. Roles are configurable — new roles/permissions can be
added without code changes to existing pages, via a `role_permissions`
pivot checked through one authorization filter/helper.

## Unique entity IDs

Every core entity (Member, Property, Project, Document, Transaction,
Invoice, Payment) gets a permanent formatted ID (`MEM-000001`, ...)
generated at creation, independent of the internal auto-increment PK and
independent of any human-readable name. File paths and URLs reference the
entity by this ID, never by name (`/portal/properties/PROP-000045`, not
`/portal/properties/Johns-House`).

## Private file security

Sensitive documents (ID scans, agreements, contracts, financial statements)
are stored under `writable/uploads/...` — outside the public webroot,
protected by a deny-all `.htaccess` as defense-in-depth for the eventual
Apache/cPanel deploy. They are only ever served through an authenticated
controller action that checks: authentication -> permission -> ownership ->
authorize -> stream. No direct public URL to a private file will exist.

Public-safe images (avatars, property listing photos, CMS media) live under
`public/uploads/...` and are served directly.

## Open decisions to confirm before Phase 1

1. **Visual design system** — dark forest green / faded black gradient
   theme, logo generated from Bootstrap Icons, Perfex-CRM-inspired admin UI
   (per user instruction) — not yet designed.
2. **Database ERD** — `docs/04_Database_Design` is currently empty; needs
   the full entity/relationship pass (Members, Properties, Projects,
   Finance, Content, Documents, Notifications, Audit) before migrations
   are written.
3. **Roles/permissions matrix** — the concrete list of roles and their
   exact permission grants (`docs/14_User_Roles`) needs to be agreed, not
   just the categories named in the spec.
4. **Membership categories** — confirm Pioneer/Prime/General as the
   initial seed set (matches the spec's example) or a different set
   specific to Barina Green City.
