🧠 Brain — Kennisbank
Alle lessen die agents hebben geleerd
20
Totale lessen in geheugen
PER CATEGORIE
architectuur
9
security
5
code
6
RECENTE GLOBALE LESSEN
waarschuwing
code
22 Jun 11:36
Alle bestanden beginnen met declare(strict_types=1). Sessievariabelen worden altijd gecast: (int)($_SESSION['user_id'] ?? 0), (string)($_SESSION['role'] ?? ''), (int)($_SESSION['team_id'] ?? 0). Null-safety via ?? operator is universeel patroon.
Bron: coachone
waarschuwing
security
22 Jun 11:36
Content-Type header wordt expliciet gezet in pagina's die geen layout_start.php gebruiken: header('Content-Type: text/html; charset=utf-8'). API-endpoints zetten 'application/json'. session_secure.php zet Cache-Control: no-store headers op API-error responses. Pagina's die session_start() aanroepen moeten dat VOOR enige output doen.
Bron: coachone
info
architectuur
22 Jun 11:36
Onboarding-pagina's (zoals onboarding_step1.php) zijn partial-includes die verwachten dat de parent (onboarding.php) variabelen als $step, $profileDraft en helpers als co_onboarding_csrf_input(), co_onboarding_step_url(), co_onboarding_checked() beschikbaar maakt. Ze staan in dezelfde map als hun parent-controller.
Bron: coachone
info
architectuur
22 Jun 11:36
layout_end.php laadt scripts in vaste volgorde: jquery.min.js → bootstrap.bundle.min.js → perfect-scrollbar.js → metisMenu.min.js → apexcharts.min.js → main.js. Daarna wordt window.CSRF_TOKEN gezet en eigen sidebar/menu-logica geïnitialiseerd (GEEN MetisMenu.init, eigen mm-active class-logica).
Bron: coachone
waarschuwing
code
22 Jun 11:36
Functies/helpers worden defensief geladen met function_exists() checks: if (function_exists('csrf_get_token')) / if (function_exists('ensure_trainer_team')) etc. Dit voorkomt fatal errors als een include-bestand een oudere versie is of een functie ontbreekt. Altijd fallback-paden voorzien.
Bron: coachone
waarschuwing
security
22 Jun 11:36
JSON output naar HTML/JS gebruikt altijd json_encode met veilige flags: JSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_QUOT|JSON_HEX_AMP voor inline script-blokken (layout_end.php). Losse API/data JSON gebruikt JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES (safe_json helper).
Bron: coachone
info
code
22 Jun 11:36
layout_start.php bouwt dynamische body-classes op basis van rol en pad: 'co-app', 'role-{role}', 'page-{filename}', 'ctx-trainer'/'ctx-speler', en 'dashboard' als het een dashboard is. $layoutTheme is 'dark' (default) of 'light'. $teamAccent is hex-kleur uit sessie of fallback '#365CFF'.
Bron: coachone
waarschuwing
architectuur
22 Jun 11:36
Trainer-pagina's halen teamcontext op via ensure_trainer_team($pdo, $trainerId) of get_trainer_team($pdo, $trainerId) met try/catch fallback naar sessiewaarden. Speler-pagina's gebruiken co_p_context($pdo). Ouder-pagina's gebruiken co_o_children($pdo, $guardianId) + co_o_seed_parent_team_session(). Club-pagina's gebruiken require_club_access($pdo, $allowedRoles) die een $ctx array retourneert met club_id en role.
Bron: coachone
waarschuwing
code
22 Jun 11:36
Schema-detectie is runtime en defensief: kolommen en tabellen worden gecheckt via INFORMATION_SCHEMA queries of helpers (co_p_col, co_p_table, table_exists) voordat ze in queries gebruikt worden. Missende kolommen worden stilzwijgend overgeslagen zodat oudere database-schema's niet crashen.
Bron: coachone
waarschuwing
architectuur
22 Jun 11:36
Profielfoto's worden NOOIT direct als pad geserveerd maar altijd via /media/profile_photo.php?player_id=X endpoint. De functie avatar_url_by_player_id() of directe URL-constructie '/media/profile_photo.php?player_id=' . $id wordt gebruikt. Foto's staan in private storage, niet in public webroot.
Bron: coachone
kritiek
architectuur
22 Jun 11:36
Standaard include-volgorde bovenaan elke pagina is: 1) security_headers.php (optioneel), 2) session_start() of session_secure.php, 3) config.php, 4) db.php, 5) csrf.php, 6) module-specifieke helpers (_player_ui.php, _ouder_ui.php, entitlements.php, club_guard.php). De volgorde session → config → db → csrf is universeel en mag niet afwijken.
Bron: coachone
kritiek
security
22 Jun 11:36
session_secure.php maakt onderscheid tussen API-requests (/api/*) en pagina-requests. API's krijgen JSON 401 responses via ss_api_json_exit(), pagina's krijgen redirects naar /public/login.php via ss_redirect(). Hijack-checks (IP/UA) worden NIET op /api/* uitgevoerd om false positives door IP-wisselingen te voorkomen.
Bron: coachone
kritiek
architectuur
22 Jun 11:36
db.php zoekt credentials in strikte volgorde: 1) environment variables (DB_HOST/DB_PORT/DB_NAME/DB_USER/DB_PASS), 2) secrets file buiten webroot (/private_storage/config/db_secrets.php via vhost root, dan docroot, dan CLI fallback), 3) legacy fallback in includes/db_secrets.php. Wachtwoorden staan NOOIT in db.php zelf.
Bron: coachone
kritiek
security
22 Jun 11:36
CSRF heeft twee systemen: globaal via csrf_token()/verify_csrf_token() en scoped via csrf_get_token('scope')/csrf_verify('scope', $token). layout_end.php zet window.CSRF_TOKEN via json_encode met JSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_QUOT|JSON_HEX_AMP voor JS fetch-calls. Tokens worden opgeslagen als ['value'=>..., 'ts'=>time()] in $_SESSION met TTL-rotatie.
Bron: coachone
kritiek
code
22 Jun 11:36
Database queries gebruiken altijd prepared statements via $pdo->prepare() met positional (?) of named (:param) parameters. Kolomnamen worden nooit via user-input samengesteld. Dynamische kolom-selectie gebeurt via schema-checks (INFORMATION_SCHEMA of co_p_col helper) en wordt hardcoded in de query gebouwd.
Bron: coachone
kritiek
architectuur
22 Jun 11:36
Elke rolmodule heeft een eigen UI-helper bestand: speler/_player_ui.php (co_p_* functies zoals co_p_context, co_p_col, co_p_table), ouder/_ouder_ui.php (co_o_* functies zoals co_o_require_parent, co_o_children, co_o_nav, co_o_css, co_o_team_card), club/club_guard.php (require_club_access). Trainer gebruikt entitlements.php + lineup_formations.php.
Bron: coachone
waarschuwing
code
22 Jun 11:36
De escape-helper h() wordt op minstens drie plaatsen gedefinieerd (layout_start.php, entitlements.php, inline in pagina's). Elke pagina die h() nodig heeft vóór layout_start.php definieert een eigen fallback: if (!function_exists('h')) { function h($v): string { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); } }. Club-module gebruikt e() als alternatieve naam met identieke implementatie.
Bron: coachone
kritiek
architectuur
22 Jun 11:36
Na db.php is $pdo beschikbaar als globale PDO-instantie. Na session_secure.php zijn $_SESSION['user_id'], $_SESSION['role'], $_SESSION['team_id'], $_SESSION['team_name'], $_SESSION['username']/['user_name'] beschikbaar. Na layout_start.php zijn $role, $lang, $teamName, $userName, $userInitial, $teamAccent, $homeHref, $layoutTheme beschikbaar.
Bron: coachone
kritiek
security
22 Jun 11:36
Authenticatie volgt altijd hetzelfde patroon: $_SESSION['role'] wordt gecheckt direct na includes. Trainer/admin: in_array(($_SESSION['role'] ?? ''), ['trainer', 'admin'], true). Speler: ($_SESSION['role'] ?? '') !== 'speler'. Ouder: via co_o_require_parent(). Club: via require_club_access($pdo, ['club_admin', 'head_youth', 'club_staff']). Bij falen altijd header('Location: /public/login.php'); exit;
Bron: coachone
kritiek
architectuur
22 Jun 11:36
Layout wordt gestart met require_once __DIR__ . '/../includes/layout_start.php' (na alle logica/data-ophaling) en afgesloten met require_once __DIR__ . '/../includes/layout_end.php'. Alle PHP-logica, queries en variabelen moeten VOOR layout_start.php staan. HTML/output komt ertussen.
Bron: coachone