Administration
This page is the control panel for the people who set up, secure, and govern Patrol — system administrators, security managers, Data Protection Officers (DPOs), and support leads. It covers the permissions matrix, the module and AI toggles, Locations, the CSV/PDF reports, the background jobs, incident alerts, the public reporting channel, the governance/retention layer, and how to switch on AI-assist responsibly. Day-to-day guard tasks live on the Daily Operations page; exact fields, tables, and screens are on the Data & Screen Reference.
Audience & prerequisites
Three roles do the work described here:
- System administrator — enables the module, runs migrations, grants permissions, wires up alerts, and manages the scheduler that runs the cron jobs.
- Security manager / supervisor — owns Locations, Reports, the public-report triage queue, and the operational settings.
- Data Protection Officer (DPO) / privacy officer — owns Governance: retention policies, legal holds, data-subject requests, the disclosure log, and the decision to enable AI-assist.
The setup order is always the same: enable the module → grant permissions → create your Locations → configure alerts and (optionally) governance/AI. Full-account admins bypass every permission check, so grant scoped roles to everyone else rather than making people admins.
Enabling the module
- Open Settings → Manage Modules and switch on Patrol. This flips the
module_patrolsetting to1. Every controller, sidebar entry, public endpoint, and cron job checks this flag first — when it is off, the whole module goes dark and the six jobs skip themselves. - Apply the module database tables with
php erpat migrate:modules(tracked in the per-modulemigrations_patroltable). The first migration seeds one default site — Main Site (codeMAIN) — so you have somewhere to log against immediately. - Apply the single core migration with
php erpat migrate:latest. It addsnotifications.patrol_incident_id(so an alert can deep-link straight to an incident) and registers the two Patrol notification events. This is Patrol's only touch on core tables. - Grant permissions (below), then have a supervisor build out Locations.
tenant_id; site_id is the intra-tenant location key. Run php erpat migrate:modules and migrate:latest against every tenant that should have Patrol, and enable module_patrol per tenant.
Permissions matrix
Patrol owns its own RBAC keys (category “Security: Patrol” in the Roles editor); they appear only while the module is enabled. Keys are stored by name, so once shipped they are frozen. patrol is the module Enable toggle; the remaining keys gate each area, with the usual _create / _update / _delete family per area. A handful of keys are deliberately separate because they guard sensitive powers — grant them narrowly.
| Permission key | What it grants |
|---|---|
| Module & dashboard | |
patrol | Module access (the Enable toggle). Required for every Patrol screen. |
patrol_dashboard | View the Patrol dashboard. |
| Activity Log (blotter) | |
patrol_log · _create · _update · _delete | View, add, amend (creates a new version), and delete blotter entries. |
| Visitor management | |
patrol_visitor · _create · _update · _delete | View; register/check-in, invites and pass issue; check-out/deny/pass-revoke; delete. |
| Incident register | |
patrol_incident · _create · _update · _delete | View, create, update (people, tasks, amendments), and delete incidents. |
patrol_incident_acknowledge | Move an incident to acknowledged. |
patrol_incident_close | Close / reopen (and archive) an incident. |
| Evidence & sensitive controls | |
patrol_evidence_view | See restricted incidents and evidence. Without it, restricted records are hidden from lists, views, reports, and AI. |
patrol_evidence_manage | Add evidence and record chain-of-custody events. |
patrol_legal_hold | Place and release legal holds (also used by Governance). |
| Shifts, guards & handover | |
patrol_shift · _create · _update | Shifts, the On-Duty panel, and guard assignments. |
patrol_guard · _create · _update · _delete | Guard roster and license tracking (update also gates licenses). |
patrol_handover · patrol_handover_acknowledge | Submit shift handovers; acknowledge an incoming handover. |
| Rounds & routes | |
patrol_route · _create · _update · _delete | Build routes and checkpoints (update also gates checkpoints). |
patrol_run · patrol_run_execute | View rounds; start / scan / complete / abort a round. |
| Assets & equipment | |
patrol_asset · _create · _update · _delete | Register and manage equipment. |
patrol_asset_assign | Issue and return equipment. |
| Locations & reports | |
patrol_location · _create · _update · _delete | Manage Sites / Zones / Gates / Posts. |
patrol_report_export | Open the Reports page and run the CSV / PDF exports. |
| Public reporting | |
patrol_public_report | View public reports (defined for reference). |
patrol_public_report_triage | Work the triage queue: set status, correspond, and convert to an incident. |
| Governance / retention / DSAR | |
patrol_retention | Governance page + retention policies. Also the area gate for the whole Governance page. |
patrol_privacy_request | Log and manage data-subject (privacy) requests. |
patrol_disclosure | Record entries in the disclosure log. |
| AI-assist | |
patrol_ai | Request AI suggestions (only works when AI-assist is switched on). |
patrol_ai_approve | Approve an AI suggestion before it can be applied. |
Applying an approved AI suggestion additionally requires patrol_incident_update. Converting a public report into an incident additionally requires patrol_incident_create.
Module settings & toggles
Three named toggles govern the whole module, plus three timing knobs:
| Setting | Default | Effect |
|---|---|---|
module_patrol | Set by Manage Modules | Master on/off. Gates every screen, public endpoint, and cron job. |
module_patrol_ai | Off (not seeded) | Switches on the AI-assist surface. See AI-assist. |
patrol_ai_dpa | Off (not seeded) | One-time DPA acknowledgement required before any AI request. Only an admin can accept it. |
patrol_escalation_minutes | 15 | Minutes an unacknowledged critical incident may sit before the escalation job alerts. |
patrol_license_expiry_days | 30 | How far ahead the license job flags guard licenses due to expire. |
patrol_round_grace_minutes | 15 | Grace added to a route’s estimated time before a round counts as overdue. |
15 / 30 / 15. To change one, add it as a system setting with your value; the module picks it up on the next run. No migration re-run is needed.
Locations admin
Locations are the physical hierarchy — Sites → Zones → Gates → Posts — that Routes, Checkpoints, Shifts, and Rounds hang off. They live on one page (patrol_settings) with a tab per entity, gated by patrol_location (plus _create / _update / _delete).
- Sites — a building, compound, or property. Main Site (
MAIN) is seeded; each site has a unique code and timezone. - Zones — areas inside a site (lobby, basement, perimeter).
- Gates — entry/exit points, direction in / out / both.
- Posts — guard positions: fixed, roving, or gate.
Set these up before building routes or scheduling shifts — checkpoints, guards, and runs all reference a site.
Reports & exports
The Reports page (patrol_reports, gated by patrol_report_export) produces two server-side exports. Both reuse the live activity and incident data — they never fork the queries — and default to the last 7 days; you can pass a start date, end date, and site.
- Daily Activity Report — CSV (
export_activity_csv). Reference, time, category, location/post, summary, narrative, action taken, and reporter. The CSV is formula-injection safe: any cell that could be read as a spreadsheet formula is neutralised, so opening the file in Excel is safe. - Incident Register — PDF (
export_incidents_pdf, A4). Restricted incidents are excluded unless the person running the export holdspatrol_evidence_view.
The list screens also carry the standard on-screen table export (copy / spreadsheet columns) for quick pulls; the two exports above are the governed, server-side reports.
Incident alerts (notifications)
Patrol registers two notification events (category Patrol): patrol_incident_raised (fired on incident creation when the “notify” box is ticked) and patrol_incident_escalated (fired by the escalation job). Both deep-link straight to the incident and default to in-app on, email off.
Cron jobs
Patrol ships six background jobs. All run per tenant, are enabled by default, and self-gate on module_patrol (they do nothing while the module is off). They only fire if your ERPat scheduler is calling the Advanced Cron runtime — inspect them with php erpat cron:list, tick the scheduler with php erpat cron:tick, and run one on demand with php erpat cron:run <slug>.
| Job slug | Cadence | What it does |
|---|---|---|
patrol_escalate_incidents | Every 5 min */5 * * * * | Escalates a critical, still-open incident left unacknowledged past patrol_escalation_minutes (15). Records an escalation action and fires patrol_incident_escalated. De-dupes so it only escalates once. |
patrol_missed_rounds | Every 15 min */15 * * * * | Flags an in-progress round overdue past its route estimate + patrol_round_grace_minutes (15). Logs an overdue warning once. |
patrol_asset_overdue | Hourly 0 * * * * | Flags issued equipment past its expected-return time. Logs an overdue warning once. |
patrol_chain_verify | Daily 02:30 30 2 * * * | Read-only re-walk of the daily hash chains for blotter entries, incidents, and handovers. Any break (deleted, reordered, or altered row) writes a CRITICAL chain_break log. |
patrol_license_expiry | Daily 03:00 0 3 * * * | Flags guard licenses expiring within patrol_license_expiry_days (30), once per license. |
patrol_retention_sweep | Daily 04:00 0 4 * * * | Applies active retention policies (see Governance). Does nothing until a DPO configures one. |
Public security reporting
Patrol includes an account-free channel where residents or the public report a concern and track it with a one-time code. It is served by a public, sessionless endpoint and is anonymity-capable and PII-minimised by design.
The public URL
- The form lives at
/patrol-reportand, for a specific tenant,/patrol-report/{company_key}(the tenant’s company key resolves the right database, the same way the kiosk and cron URLs do). Publish that link on your community site, a QR poster, or a gate sign. - Reporters check status at
/patrol-report/track/{company_key}/{code}— a PII-free page that never shows reporter details or internal staff notes. - The endpoint returns a generic “not found” for a bad or disabled tenant, so it cannot be used to probe which tenants exist.
Anonymity & anti-abuse
- One-time tracking code. The raw code is shown to the reporter once and never stored — only its SHA-256 hash is kept, and lookups are constant-time. If a reporter loses the code, it cannot be recovered.
- Anonymous mode nulls the reporter name and contact. The reporter’s IP is never stored in the clear — only a SHA-256 hash, used solely for throttling.
- Throttling. Submissions are capped per IP: 5 per hour (session-backed) with a database backstop that blocks an IP after 10 submissions in 60 minutes.
Triage
Staff work incoming reports on the Public Reports page (patrol_public_reports, gated by patrol_public_report_triage): read the queue (with a “new” count), reply to the reporter (public message) or add internal-only notes, and set status new / triaged / closed / spam. Convert to incident (which also needs patrol_incident_create) maps urgency to severity — low→low, normal→medium, high→high, emergency→critical — creates an incident with source public, links the two, and marks the report linked.
Governance, retention & disclosure
The Governance page (patrol_governance) is the DPO’s compliance layer, with four tabs. The area gate is patrol_retention; each tab has its own key.
- Retention policies (
patrol_retention) — one rule per record type (activity log, incident, visit, public report), an action (anonymize, soft delete, or purge), and a retention period in days. - Legal holds (
patrol_legal_hold) — freeze a specific record, or a whole record type within a date range, so the retention sweep can never touch it. Legal-hold incidents also cannot be deleted. - Data-subject requests / DSAR (
patrol_privacy_request) — log access, correction, and erasure requests with a due date, and track them to fulfilled or rejected. - Disclosure log (
patrol_disclosure) — record every release of records to a third party and its legal basis (subpoena, law enforcement, consent, legal obligation, other).
patrol_retention_sweep job only acts on a policy that a DPO has both set a period on and switched to active. This is deliberate — no data is ever aged out by accident.
When a policy runs, the sweep respects strong safety rails: it excludes anything under an active legal hold, it never purges a record that has a logged disclosure or (for incidents) still has evidence, and it caps each run. Every run writes a deletion certificate to the audit log and stamps the policy’s last-run time. Alongside it, the daily patrol_chain_verify job re-checks the tamper-evident hash chains and raises a CRITICAL log on any break.
Activating a retention policy responsibly
- Agree the retention period for each record type with your legal/compliance owner (e.g. keep visitor logs N days).
- On the Retention policies tab, edit the placeholder for that record type: choose the action (start with anonymize or soft delete before ever using purge), set the days, and switch it active.
- Place any needed legal holds first so litigation-relevant records are frozen before the sweep runs.
- Let the daily sweep run, then check the deletion certificate in the audit log to confirm what was acted on.
AI-assist (ships disabled)
Patrol can draft an incident narrative, suggest a classification, or write a handover briefing using the existing AkbAI proxy — but it is human-in-the-loop and switched off by default. AI never writes an incident: output is held pending explicit human approval, and applying it only ever adds an action note to the incident.
Three gates must all pass before a single request can be made:
- Module & permission —
module_patrolon and the user holdspatrol_ai. module_patrol_ai= 1 — while off, the page shows a “disabled” notice.patrol_ai_dpa= 1 — a one-time Data Processing Agreement acknowledgement that only an administrator can accept.
Before any text leaves the tenant it is PII-redacted — emails, phone numbers, long ID numbers, and named individuals are masked. Requests run only against non-restricted incidents (using a restricted incident additionally needs patrol_evidence_view). A reviewer with patrol_ai_approve approves an output; a user with patrol_incident_update then applies the approved text as an ai_suggestion action. Every step is audited, and if AkbAI is not configured the request fails gracefully.
Enabling AI-assist responsibly
- Confirm your organisation’s data-processing position with your DPO, and that AkbAI is configured for the tenant.
- Switch on
module_patrol_ai. - Have an administrator open the AI page and accept the DPA (sets
patrol_ai_dpa). - Grant
patrol_aito the officers who may request suggestions, andpatrol_ai_approveto the reviewers who may approve them — keep those two roles separate. - Treat every suggestion as a draft: review, edit, and only then apply it as an incident note.
Audit & integrity notes
Every mutation across the module writes an audit entry (system-log category Security), times are stored in UTC and shown local, and everything is soft-deleted. Reference numbers (EVT-, INC-, VIS-, HND-, RUN-, PSR-, LGH-, PRV-, DSC-) are minted once and never reused; amendments create a new version rather than editing in place. Administrators do not need to manage any of this — it is automatic — but it is why some records cannot be edited or hard-deleted. The tables, columns, and log components behind each area are catalogued on the Data & Screen Reference.
Related pages
- Getting Started — first-run setup and enabling the module.
- Daily Operations — the guard-facing workflows this page governs.
- Data & Screen Reference — every table, route, permission, and screen.
- Research & Evidence — the source files behind these facts.
- FAQ & Troubleshooting — “why don’t alerts arrive?”, “why can’t I edit this?”, and more.