# OptikRapor v0.9.0 — Firma/Şube Yönetimi
Preconditions: PostgreSQL migrations 001,002,003,004 already installed. Run 005_tenant_admin.sql using optikrapor_owner (backup first). Ensure created user has an active company_admin user_memberships row with branch_id NULL; branch_manager cannot access company-wide editing.
## Signing secret — ONE TIME, confidential
Using DBeaver and optikrapor_owner, query:
SELECT secret FROM optikrapor_private.auth_signing_keys WHERE id=1;
This secret is sensitive. Do not share it in a chat, terminal logs, screenshots or GitHub. Using cPanel File Manager and the existing app/config/db.local.php (never the tracked db.local.example.php), add a new element inside the return array:
'rls_signing_secret' => 'PASTE_96_HEX_CHAR_SECRET_HERE',
The 96 hex chars must remain private and should never appear in browser-visible files. Protect app/config with web-server access-deny, test a direct request to /app/config/db.local.php returns 403. Prefer storing config outside web root at a later deployment hardening stage. Note: reading/handling this secret via PHP means a compromised PHP runtime can impersonate an authenticated DB tenant; this is not a substitute for overall host security. Never use the DB owner credential in PHP.
## Application files
app/src/Core/TenantDb.php introduces short-lived signed transaction context and rollback.
app/manage.php serves tenant admin company/branch forms with CSRF, no direct writes to tenant tables. /app dashboard links to /app/manage.php. Login still needs brute-force defense and hardening.
## Verification
1. Back up DB.
2. Install 005 migration once as owner.
3. Add secret to local config securely.
4. Run OptikRapor-Guncelle.bat and FTP-KR sync only app/ files.
5. Sign in as ICE Optik company_admin. Open /app/manage.php and verify firm details / branch list and small edit.
6. Test with non-admin account: denied. Test no secret: management read returns 503.
7. Do not put real customer data until RLS cross-tenant tests and production hardening are complete.
No further migration SQL should be run through PHP or FTP.
