# Websites System Architecture Standard

## Purpose

This standard defines a consistent filesystem architecture for all applications hosted below the Websites workspace. Its goals are predictable ownership, clear public/private boundaries, reusable system tooling, safer deployment configuration, and auditable application structure.

The standard applies to:

```text
/home/intel145/websites/
```

The two top-level application domains are:

```text
websites/system/     Shared platform code, tools, documentation, and policies
websites/apps/       Independently deployable applications
```

## Top-level layout

```text
/home/intel145/websites/
├── system/
│   ├── bin/
│   ├── config/
│   ├── docs/
│   ├── lib/
│   ├── policies/
│   ├── reports/
│   ├── templates/
│   └── tests/
└── apps/
    ├── appname/
    └── anotherapp/
```

`system/` is shared operational infrastructure. `apps/` contains application roots. No app may write into `system/` at runtime, except through explicitly approved report or log interfaces.

## Directory ownership and purpose

| Directory | Owner | Purpose | Public HTTP access |
|---|---|---|---|
| `websites/system/` | platform/system owner | Shared tools, policies, reusable libraries, docs, templates | Deny by default |
| `websites/system/bin/` | platform/system owner | POSIX shell tools, audit runners, maintenance commands | Never public |
| `websites/system/config/` | platform/system owner | Shared non-secret configuration and app registry | Never public |
| `websites/system/docs/` | platform/system owner | Architecture, operations, standards, FAQs, runbooks | Never public |
| `websites/system/lib/` | platform/system owner | Shared PHP libraries or reusable internal code | Never public |
| `websites/system/policies/` | platform/system owner | Audit policies, naming exceptions, route policies | Never public |
| `websites/system/reports/` | platform/system owner | Generated audit reports; retention-managed | Never public |
| `websites/system/templates/` | platform/system owner | Scaffolds for new apps and standard documents | Never public |
| `websites/system/tests/` | platform/system owner | System-tool tests and fixtures | Never public |
| `websites/apps/` | platform/system owner | Parent container for independently deployable applications | Not a public directory listing |
| `websites/apps/<app>/` | application owner | One application root | Public only through approved routes/assets |

## Application root standard

Every application is a single directory directly beneath `apps/`:

```text
websites/apps/<appname>/
```

`<appname>` must use lowercase letters, digits, and underscore only:

```text
Valid:   defapp, client_portal, reports2
Invalid: DefApp, client-portal, client.portal
```

An app root may contain only approved root files and directories.

```text
websites/apps/<appname>/
├── admin/
├── config/
├── css/
├── docs/
├── includes/
├── js/
├── pages/
├── public/
├── src/
├── storage/
├── tests/
├── vendor/
├── app.php
├── index.php
├── README.md
└── .gitignore
```

Not every application needs every directory. Empty/unneeded directories should not be created merely to satisfy appearance.

## Application directory rules

| App directory | Purpose | HTTP policy | Rules |
|---|---|---|---|
| `admin/` | Authenticated administrative endpoints and controllers | Public route only through application authorization | Must enforce server-side admin authorization and CSRF for state changes |
| `config/` | App configuration, policy arrays, route maps | Deny direct access | No secrets in a public path; prefer environment/platform secret store |
| `css/` | Public stylesheets | Allow | External CSS contains raw CSS only; no `<style>` tags |
| `docs/` | App-specific documentation | Deny in production unless intentionally published | Do not expose internal operations/security docs by default |
| `includes/` | Reusable PHP include fragments and bootstrap helpers | Deny direct access | No full page layout roots in partials |
| `js/` | Public JavaScript modules/assets | Allow | Use lowercase file naming policy |
| `pages/` | Server-side view fragments included by public controllers/templates | Deny direct access | Must not be individually routable; must not contain `.app-wrapper` |
| `public/` | Optional explicit public document root | Allow only intended assets/entry points | Preferred for new apps when deployment supports per-app document roots |
| `src/` | PHP domain/application code and classes | Deny direct access | Class files follow class policy; no presentation-only fragments |
| `storage/` | Runtime cache, uploads, generated files, logs | Deny by default | Must be writable only where necessary; no executable uploads |
| `tests/` | Automated tests, fixtures, test helpers | Deny direct access | Not part of production routes |
| `vendor/` | Composer dependencies | Deny direct access except required autoloader through PHP | Never edit generated vendor files |
| `old/` | Deprecated legacy material during migration only | Deny direct access | Temporary; ticket/date/owner required; remove when migration completes |

## Root-file rules

| File | Purpose | Rule |
|---|---|---|
| `index.php` | Preferred public application entry point | One per application root or public root |
| `app.php` | Application bootstrap/composition entry | Not directly public unless deliberately routed |
| `README.md` | App overview and local setup | Required for maintained apps |
| `.gitignore` | Repository exclusions | Required where Git is used |
| `.env` | Local secret configuration only | Never commit; never publicly serve |
| `composer.json` | Dependency declaration | Allowed when Composer is used |
| `composer.lock` | Locked dependency graph | Commit for deployed applications using Composer |

Legacy entry names such as `defapp.index.php` or `defapp.template.php` are permitted temporarily only through an app policy exception. New applications should use `index.php` and a clearly named bootstrap/template structure.

## Public/private boundary

The web server must expose only intentionally public routes and assets. Application source directories are not public content.

### Nginx production policy

Nginx configuration or hosting policy must deny direct access to application-internal paths such as:

```text
/<app>/config/
/<app>/includes/
/<app>/pages/
/<app>/src/
/<app>/storage/
/<app>/tests/
/<app>/vendor/
/<app>/old/
/<app>/docs/
```

Public asset paths may include:

```text
/<app>/css/
/<app>/js/
/<app>/images/
/<app>/assets/
```

Do not rely on `.htaccess` in production Nginx deployments.

## Naming standard

### Directories

Directory names use lowercase letters, digits, and underscore only:

```text
Valid:   app_data, system_tools, reports2
Invalid: app-data, app.data, AppData
```

### Files

File base names use lowercase letters and digits only. The final dot before the extension is allowed; hyphens and underscores are not allowed in file base names:

```text
Valid:   breadcrumbs.php, navbarclean.css, admintools.js
Invalid: navbar-clean.css, navbar_clean.css, NavbarClean.css
```

### Exceptions

A legacy file/directory must be listed in an app policy exception list with:

- path
- reason
- owner
- review date
- migration target, if applicable

Exceptions are warnings, not silent exclusions.

## Component ownership

Every global layout component has one markup owner:

| Component | Single owner |
|---|---|
| `.app-wrapper` | primary application template only |
| `.app-header` | primary template or one dedicated header component |
| `#sidebar` | primary template or one dedicated sidebar component |
| `.app-main` | primary application template only |
| `#layout-header` | primary page template only |
| `#app-content` | primary page template only |
| `#footer` | primary template or one footer component |
| `#modal` | one global modal component |
| `#liveToast` | one global toast component |

Files in `pages/` and `includes/` may own local fragments only. They must not create a second `.app-wrapper`, `.app-main`, `#sidebar`, or other global root component.

## System application registry

Create a system-owned registry at:

```text
websites/system/config/apps.registry.php
```

Example:

```php
<?php
declare(strict_types=1);

return [
    'defapp' => [
        'root' => '/home/intel145/websites/apps/defapp',
        'public_base_path' => '/defapp',
        'entry_file' => 'defapp.index.php',
        'legacy_exceptions' => [
            'defapp.index.php',
            'defapp.template.php',
            'navbar.admin.php',
            'sidebar.test.php',
        ],
    ],
];
```

The registry is system-owned. Browser clients must never supply arbitrary roots, filesystem paths, or route prefixes to audit tools.

## Audit requirements

A generic system audit must validate:

- App name matches the naming rule.
- Resolved app root remains below `websites/apps/`.
- Required public entry point exists or is registered.
- Only one active `.app-wrapper` owner exists.
- `pages/` and `includes/` do not contain global layout roots.
- External CSS does not contain HTML `<style>` tags.
- Naming policy violations are listed with paths and suggested names.
- Backup/editor residue and sensitive file types are listed for review.
- Private route checks classify `200` as fail and `403`, `404`, or `406` as protected.
- Unreliable request outcomes such as timeout/5xx are errors, not passes.
- Reports contain findings, rules, why the rule exists, remediation, and exact paths/lines when detail mode is enabled.

## New-app creation checklist

1. Choose a valid lowercase/underscore app name.
2. Create `apps/<appname>/` from the approved system template.
3. Register the app in `system/config/apps.registry.php`.
4. Create one public entry point.
5. Define public asset paths and internal directory policy.
6. Add Nginx/hosting rules for internal source paths.
7. Add app README and route policy.
8. Run system architecture audit and naming audit.
9. Commit only reviewed source and policy changes.

## Golden rules

1. `system/` is shared platform infrastructure; `apps/` contains deployable applications.
2. Every app has exactly one root under `apps/<appname>/`.
3. A web server exposes public routes/assets, never arbitrary source directories.
4. Nginx production security belongs in Nginx/hosting configuration, not `.htaccess`.
5. Every global layout component has one markup owner.
6. Audit tools are read-only, allowlisted, and path-contained.
7. System scripts are POSIX `sh` unless a documented Bash requirement exists.
8. Legacy exceptions are explicit, owned, dated, and reviewable.
